summaryrefslogtreecommitdiff
path: root/Docs/Tutorial-MySQL-final.txt
blob: bd52554a6111db8436f4c7d04cc0c62f8497d517 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
8 Tutorial MySQL
=======================

Este capítulo ofrece un tutorial de introducción a MySQL, mostrando cómo usar el programa cliente
mysql para crear y usar una simple base de datos. mysql (al que algunas veces nos referimos como
"monitor terminal" o simplemente "monitor") es un programa interactivo que te permite conectarte a
un servidor MySQL, ejecutar consultas y observar los resultados. mysql puede ser usado también en
modo batch: escribes tus consultas en un fichero de texto, para después pedirle a mysql que
ejecute el contenido del fichero. Se cubren aquí esas dos formas de usar de usar mysql.

Para ver una lista de opciones proporcionadas por mysql, lánzalo con las opción --help :

    shell>  mysql --help

Este capítulo asume que mysql está instalado en tu máquina, y que hay disponible un servidor al que
te puedes conectar. Si esto no es así, contacta con tu administrador MySQL. (Si el administrador
eres tú, necesitarás consultar otra sección de este manual).

El capítulo describe el proceso completo de configurar y usar una base de datos. Si estás interesado
sólo en acceder una base de datos ya existente, querrás saltar las secciones que describen cómo
crear la base de datos y las tablas que la contienen.

Dado que este capítulo es un tutorial básico, se dejarán en el tintero muchos
detalles. Consulta las secciones relevantes del manual para más información sobre los temas
aquí cubiertos.


8.1 Conectando y desconectando del servidor
=============================================


Para conectarse al servidor, generalmente necesitarás facilitar un nombre de usuario MySQL cuando
lances el cliente mysql y, lo más probable, también un password. Si el servidor se está ejecutando
en una máquina distinta a la que estás conectado, necesitarás especificar también un nombre de
host. Contacta con tu administrador para averiguar qué parámetros de conexión necesitas usar para
conectar (es decir, qué host, nombre de usuario y password usar). Una vez que conozcas los
parámetros adecuados, deberás ser capaz de conectar de la siguiente forma:

shell> mysql -h host -u user -p
Enter password: *******
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 459 to server version: 3.22.20a-log

Type 'help' for help.

mysql> 

El prompt te indica que mysql ya está listo para la introducción de comandos.

Algunas instalaciones MySQL permiten a los usuarios conectarse como usuarios "anonymous" (sin
nombre) al servidor ejecutándose en el host local. Si este es el caso en tu máquina, deberías ser
capaz de conectar a ese servidor invocando mysql sin ninguna opción:

shell> mysql

Una vez que hayas conectado con éxito, puedes desconectarte en cualquier momento tecleando QUIT en
el prompt mysql>  :

mysql> QUIT
Bye

También puedes desconectar tecleando control-D.

La mayor parte de los ejemplos en las siguientes secciones asumen que estás conectado al
servidor. Lo indicarán por el prompt mysql>


8.2 Haciendo consultas
========================

Asegúrate de que estás conectado al servidor, como se ha discutido en secciones anteriores. El
hacerlo no implica que tengas seleccionada ninguna base de datos con la que trabajar, pero está
bien. En este punto, es más importante averiguar un poco sobre cómo lanzar consultas que lanzarse
directamente a la creación de tablas, cargar datos en ellas y recuperar los datos de las
mismas. Esta sección describe los principios básicos de la entrada de comandos, usando varias
consultas que puedes probar para familiarizarte con la forma de trabajo de mysql.

Aquí presentamos un comando simple que pide al servidor que nos diga su número de versión y fecha
actual. Tecléalo como se muestra a continuación siguiendo el prompt mysql> y pulsa la tecla RETURN:


mysql> SELECT VERSION(), CURRENT_DATE;
+-----------+--------------+
| version() | CURRENT_DATE |
+-----------+--------------+
| 3.22.23b  | 2000-01-05   |
+-----------+--------------+
1 row in set (0.06 sec)

mysql> 

Esta consulta ilustra muchas cosas sobre mysql:

* Un comando consiste normalmente de una sentencia SQL seguida por un punto y coma. (Existen algunas
  excepciones donde no es necesario el punto y coma. QUIT, mencionado más adelante, es una de
  ellas. Conoceremos otras más adelante.)

* Cuando lanzas un comando, mysql lo envía al servidor para su ejecución y muestra los resultados,
  después imprime otro mysql> para indicar que está listo para otro comando.

* mysql muestra la salida de una consulta como una tabla (filas y columnas). La primera fila
  contiene etiquetas para las columnas. Las siguientes filas son el resultado de la
  consulta. Normalmente, las etiquetas de las columnas son los nombres de las columnas que has
  obtenido de la base de datos. Si pides el valor de una expresión en vez de una columna de una
  tabla (como en el ejemplo anterior), mysql etiqueta la columna usando la propia expresión.

* mysql muestra el número de filas que se han dado como resultado, y cuánto tiempo llevó la
  ejecución de la consulta, lo que te da una idea aproximada del rendimiento del servidor. Estos
  valores son imprecisos porque representan tiempo real (no tiempo de CPU o máquina), y porque están
  afectados por factores como la carga del servidor y la latencia de la red. (Por cuestiones de
  brevedad, la línea "rows in set" no se mostrará en los ejemplos posteriores de este capítulo.)

Las palabras clave pueden ser tecleadas en cualquier combinación mayúscula/minúscula. Las siguientes
consultas son equivalentes:

mysql> SELECT VERSION(), CURRENT_DATE;
mysql> select version(), current_date;
mysql> SeLeCt vErSiOn(), current_DATE;

He aquí otra consulta. Demuestra que puedes usar mysql como una calculadora sencilla:

mysql> SELECT SIN(PI()/4), (4+1)*5;
+-------------+---------+
| SIN(PI()/4) | (4+1)*5 |
+-------------+---------+
|    0.707107 |      25 |
+-------------+---------+

Los comandos vistos hasta aquí han sido relativamente cortos, sentencias de una sola línea. También puedes
insertar múltiples sentencias en una sola línea. Simplemente, termina cada una con un punto y coma:

mysql> SELECT VERSION(); SELECT NOW();

+-----------+
| version() |
+-----------+
| 3.22.23b  |
+-----------+

+---------------------+
| NOW()               |
+---------------------+
| 2000-01-05 17:33:16 |
+---------------------+

Un comando no necesita ser dado todo en una sóla línea, así pues, los comandos largos que requieran
varias lineas no son un problema. mysql determina cuando termina tu sentencia buscando el punto y
coma final, no buscando el final de la línea de entrada. (En otras palabras, mysql acepta entrada de
libre formato: recoleta las líneas de entrada pero no las ejecutahasta que vea el punto y coma.)

Aquí tenemos un simple ejemplo de múltiples líneas:

mysql> SELECT
    -> USER()
    -> ,
    -> CURRENT_DATE;
+----------------+--------------+
| USER()         | CURRENT_DATE |
+----------------+--------------+
| root@localhost | 2000-01-05   |
+----------------+--------------+

En este ejemplo, observa como cambia el prompt de mysql> a -> una vez que has insertado la primera
línea de una consulta multi-línea. Esta es la forma en que mysql indica que no ha encontrado una
sentencia completa y que está esperando por el resto. El prompt es tu amigo, dado que ofrece una
retroalimentación (feedback) significativa. Si usas ese feedback, siempre sabrás a qué está
esperando mysql.

Si decides que no quieres ejecutar un comando que está en proceso de introducción, puedes cancelarlo
tecleando \c :

mysql> SELECT
    -> USER
    -> \c
mysql> 

Observa aquí también el prompt. Ha vuelto a mysql> tras haber tecleado \c, ofreciendo un feedback
que indica que mysql está listo para un nuevo comando.

La siguiente tabla muestra cada uno de los prompts que puedes ver y resume qué es lo que significan
y el estado en el que se encontrará mysql:

Prompt	       Significado
mysql>	       Listo para un nuevo comando
    ->	       Esperando una nueva línea de una consulta multi-línea
    '>	       Esperando la siguiente línea, se ha insertado una línea que comienza con (')
    ">	       Esperando la siguiente línea, se ha insertado una línea que comienza con (")

Las sentencias multi-línea ocurren comúnmente "por accidente" cuando intentas lanzar un comando en
una única línea, pero olvidas el punto y coma del final. En este caso, mysql espera más entrada:

mysql> SELECT USER()
    ->

Si esto es lo que te ocurre (crees que has introducido una sentencia pero la única respuesta es un
prompt como ->), lo más probable es que mysql esté esperando por el punto y coma. Si no observas qué
es lo que te dice el prompt, podrías quedarte esperando un buen rato antes de enterarte de qué es lo
que sucede. Introduce un punto y coma para completar la sentencia, y mysql la ejecutará:

mysql> SELECT USER()
    -> ;
+----------------+
| USER()         |
+----------------+
| root@localhost |
+----------------+

Los prompts '> y "> ocurren durante la recogida de strings. En MySQL, puedes escribir strings
encerrados por comillas simples (') o dobles (") (por ejemplo, 'hola' o "adios"), y mysql te permite
introducir también strings que se cortan en múltiples líneas. Cuando veas un prompt como '> ó ">,
significa que has introducido una línea que contenía un string que comenzaba por (') o ("), pero que
no has introducido aún la comilla (simple o doble) de cierre. Esto está bien si realmente estabas
introduciendo un string multi-línea, pero no es lo más normal. Lo que sí es más normal, es que los
prompts '> ó "> indiquen que te has olvidado del caracter de cierre " ó '. Por ejemplo:

mysql> SELECT * FROM mi_tabla WHERE nombre ="García AND edad < 30;
    ">  

Si tecleas esta sentencia SELECT, después pulsas ENTER y esperas por el resultado, no sucederá
nada. En lugar de preocuparte, "¿por qué tarda tanto esta consulta?", observa la pista que te ofrece
el prompt "> . Esto te indica que mysql espera ver el resto de un string que aún no ha
terminado. (¿Ves el error en la sentencia? La cadena "García ha perdido las comillas de cierre.)

Llegados a este punto, ¿qué puedes hacer?. Lo más fácil es cancelar el comando. Sin embargo, no
puedes teclear simplemente \c en este ejemplo,  dado que mysql ¡lo interpretará como parte del string
que está leyendo! En vez de eso, introduce las comillas de cierre (para que mysql sepa que ya has
terminado de introducir el string), y después teclea \c :

mysql> SELECT * FROM mi_tabla WHERE nombre ="García AND edad < 30;
    "> "\c
mysql> 

El prompt vuelve a cambiar a mysql>, indicando que mysql está listo para un nuevo comando.

Es importante saber qué significan los prompts '> y ">, dado que si introduces por error un string
sin cerrar, cualquier otra línea que introduzcas serán ignoradas por mysql - ¡incluyendo una línea
que contenga QUIT! Esto puede ser bastante confuso, especialmente si no sabes que debes introducir
la comilla de cierre antes de poder cancelar el comando actual.

8.3 Creando y usando una base de datos
==========================================

Ahora que sabes como introducir comandos, es hora de acceder a la base de datos.

Supon que tienes varias mascotas en tu casa (tu pequeño "zoo") y que te gustaría llevar un control
de varios tipos de información sobre estos animales. Puedes hacerlo creando tablas que guarden tus
datos y cargandolas con la información deseada. Después puedes responder a diferentes series de
preguntas sobre tus animales extrayendo los datos de las tablas. Esta sección explica cómo hacer
todo esto:

* Cómo crear una base de datos
* Cómo crear una tabla
* Cómo cargar los datos en la tabla
* Cómo extraer información de la tabla de varias maneras
* Cómo usar múltiples tablas

La base de datos del zoo será simple (deliberadamente), pero no es difícil pensar en situaciones del
mundo real en las que se pudiera utilizar una base de datos similar. Por ejemplo, se podría usar una base
de datos como ésta en una granja para llevar un control del ganado, o por un veterinario para
controlar el historial de sus pacientes.

Usa la sentencia SHOW para averiguar qué bases de datos existen actualmente en el servidor:

mysql> SHOW DATABASES;
+----------+
| Database |
+----------+
| mysql    |
| test     |
+----------+

Probablemente, la lista de las bases de datos será diferente en tu máquina, pero las bases de datos
mysql y test es probable que se encuentren en esa lista. Se requiere la base de datos mysql pues
describe los privilegios de acceso de los usuarios. La base de datos test se ofrece como campo de
pruebas para que los usuarios prueben ahí sus teorías.

Si la base de datos test existe, intenta acceder a ella:

mysql> USE test
Database changed

Observa que USE, como QUIT, no requiere un punto y coma. (Puedes terminar este tipo de sentencias
con un punto y coma si quieres, pero no es necesario.) La sentencia USE es especial en otro sentido,
también: debe ser tecleada en una sola línea.

Puedes usar la base de datos test (si tienes acceso a ella) para los ejemplos que siguen, pero
cualquier cosa que crees en dicha base de datos puede ser eliminada por cualquiera que tenga acceso
a ella. Por esta razón, deberías pedir a tu administrador MySQL permisos para usar una base de datos
propia. Suponte que le quieres llamar zoo. El administrador necesitará ejecutar entonces la
siguiente orden:

mysql> GRANT ALL ON zoo.* TO tu_nombre;

donde tu_nombre es el nombre de usuario MySQL que tengas asignado.

ejemplo:

mysql> GRANT ALL ON zoo.* TO chessy@localhost;
Query OK, 0 rows affected (0.08 sec)


8.3.1 Creando y seleccionando una base de datos
==================================================

Si el administrador creó la base de datos para tí cuando te configuró los permisos, puedes comenzar
a usarla. En otro caso, deberás crearla tú mismo:

[chessy@bishito chessy]$ mysql -u chessy
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6 to server version: 3.22.23b

Type 'help' for help.

mysql> CREATE DATABASE zoo;
Query OK, 1 row affected (0.02 sec)


Bajo Unix, los nombres de bases de datos son sensibles a las mayúsculas/minúsculas (a diferencia de
los comandos SQL), así que deberás referirte siempre a tu base de datos con el nombre zoo, no como
Zoo, ZOO o cualquier otra variante. Es es así también para las tablas. (Bajo Windows, esta
restricción desaparece, aunque deberías referirte a las bases de datos y a las tablas usando la
misma sintaxis en tus consultas.)

Crear una base de datos no la selecciona para su uso, debes hacerlo explícitamente. Para hacer que
la base de datos zoo sea tu base de datos de trabajo, usa el comando:

mysql> USE zoo;
Database changed

Tu base de datos sólo necesita ser creada una vez, pero debes seleccionarla para usarla cada vez que
comiences una sesión mysql. Puedes hacerlo lanzando un comando USE como se ha visto en el
ejemplo. Alternativamente, puedes seleccionar la base de datos desde la línea de comandos cuando
lanzas mysql. Simplemente especifica su nombre tras los parámetros de conexión que hayas
escrito. Por ejemplo:

shell> mysql -h host -u user -p zoo
Enter password: ********

Observa que en la línea de comandos del ejemplo, zoo no es tu password. Si quieres introducir tu
password como parámetro en la línea de comandos tras la opción -p, debes hacerlo sin teclear un
espacio en blanco intermedio (es decir, como -pmi_password, no como -p mi_password). Sin embargo, no
es recomendable poner tu password en la línea de comandos, pues hacerlo lo expone a posibles
miradas de otros usuarios conectados a tu máquina.

8.3.2 Creando una tabla
============================

Crear una tabla es la parte fácil, pero hasta este momento está vacía, como te dice la orden SHOW
TABLES:

mysql> SHOW TABLES;
Empty set (0.00 sec)

La parte más dura consiste en decidir cual va a ser la estructura de tu base de datos: qué tablas
necesitarás, y qué columnas tendrá cada una de ellas.

Querrás seguramente una tabla que contenga un registro por cada una de tus mascotas. Esta tabla
puede llamarse mascotas, y debería contener, como mínimo, el nombre de cada animal. Dado que el
nombre por sí solo no es muy interesante, la tabla debería contener otra información. Por ejemplo,
si más de una persona de tu familia tiene mascotas, probablemente quieras listar el propietario de
cada animal. También querrás guardar información descriptiva básica como puede ser la especie y el
sexo de cada mascota.

¿Qué pasa con la edad? Podría ser de interés, pero no es una buena cosa a guardar en una base de
datos. La edad cambia a medida que pasa el tiempo, lo que significa que tendrás que actualizar tus
registros a menudo. En vez de eso, es mejor almacenar un valor fijo como la edad de
nacimiento. Después, cada vez que necesites saber la edad, puedes calcularla como la diferencia
entre la fecha actual y la fecha de nacimiento. MySQL ofrece funciones para realizar cálculos
aritméticos entre fechas, por lo que esto no es difícil. Almacenar la fecha de nacimiento en lugar
de la edad tiene también otras ventajas:

* Puedes usar la base de datos para generar recordatorios de cumpleaños de mascotas. (Si crees que
  este tipo de consulta es algo tonta, observa que es la misma pregunta que necesitarás hacer en el
  contexto de una base de datos de un negocio para identificar clientes a los que pronto necesitarás
  mandar un saludo por su cumpleaños, para ese toque personal asistido por ordenador :-)

* Puedes calcular la edad en relación a fechas distintas a la fecha actual. Por ejemplo, si
  almacenas la fecha de muerte en la base de datos, puedes calcular fácilmente lo vieja que era una
  mascota cuando murió.

Seguramente puedas pensar en otros tipos de información que sería útil en la tabla mascota, pero los
identificados hasta ahora son suficientes por el momento: nombre, propietarios, especie, sexo, fecha
de nacimiento y muerte.

Usa una sentencia CREATE TABLE para especificar la estructura de tu tabla:

mysql> CREATE TABLE mascota (nombre VARCHAR(20), propietario VARCHAR(20),
    -> especie VARCHAR(20), sexo CHAR(1), nacimiento DATE, muerte DATE);

VARCHAR es una buena elección para las columnas nombre, propietario y especie dado que los valores
de estas columnas variarán su longitud. Las longitudes de estas columnas no necesitan ser iguales, y
no necesitan ser 20. Puedes elegir cualquier longitud entre 1 y 255, cualquiera que te parezca
razonable. (Si realizar una elección pobre y resulta que más adelante necesitas un campo mayor,
MySQL ofrece una sentencia ALTER TABLE.)

El sexo del animal puede ser representado en una variedad de formas, por ejemplo, "m" y "f", o
quizás "masculino" y "femenino". Es más simple usar un único caracter, "m" ó "f".

El uso del tipo de datos DATE para las columnas de nacimiento y muerte es una opción bastante
obvia. 

Ahora que ya has creado una tabla, SHOW TABLES debería producir alguna salida:

mysql> SHOW TABLES;
+---------------+
| Tables in zoo |
+---------------+
| mascota       |
+---------------+

Para verificar que tu tabla fue creada de la forma que esperabas, usa una sentencia DESCRIBE:

mysql> DESCRIBE mascota;
+-------------+-------------+------+-----+---------+-------+
| Field       | Type        | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| nombre      | varchar(20) | YES  |     | NULL    |       |
| propietario | varchar(20) | YES  |     | NULL    |       |
| especie     | varchar(20) | YES  |     | NULL    |       |
| sexo        | char(1)     | YES  |     | NULL    |       |
| nacimiento  | date        | YES  |     | NULL    |       |
| muerte      | date        | YES  |     | NULL    |       |
+-------------+-------------+------+-----+---------+-------+

Puedes usar DESCRIBE en cualquier momento, por ejemplo, si olvidas los nombres de las columnas de tu
tabla o a qué tipo de datos pertenecen.

8.3.3 Cargando datos en una tabla
=====================================

Una vez creada tu tabla, necesitas poblarla. Las sentencias LOAD DATA e INSERT son útiles para esto.

Suponte que tus registros de mascotas pueden ser descritos como se muestra más abajo. (Observa que
MySQL espera que las fechas se introduzcan en formato AAAA-MM-DD; esto podría ser diferente a lo que
estás acostumbrado.)

nombre	 propietario	especie		sexo	nacimiento	muerte
Fluffy	 Harold		gato		f	1993-02-04		
Claws	 Gwen		gato		m	1994-03-17
Buffy	 Harold		perro		f	1989-05-13
Fang	 Benny		perro		m	1990-08-27
Bowser	 Diane		perro		m	1998-08-31	1995-07-29
Chirpy	 Gwen		pájaro		f	1998-09-11
Whistler Gwen		pájaro			1997-12-09
Slim	 Benny		serpiente	m	1996-04-29

Dado que estás comenzando con una tabla vacía, una forma sencilla de poblarla consiste en crear un
fichero de texto conteniendo una fila para cada uno de tus animales, y después cargar el contenido del
fichero en la tabla con una sola sentencia.

Puedes crear un fichero de texto "mascota.txt" conteniendo un registro por línea, con valores separados
por tabuladores, y dados en el orden en el que las columnas fueron listadas en la sentencia CREATE
TABLE. Para valores perdidos (como sexos desconocidos, o fechas de muerte de animales que aún están
vivos), puedes usar valores NULL. Para representar estos en tu fichero de texto, use \N. Por
ejemplo, el registro para Whistler el pájaro sería algo como esto (donde el espacio en blanco entre
valores es un simple caracter de tabulación):

Whistler   Gwen	     pájaro     \N	1997-12-09	\N

Para cargar el fichero de texto "mascota.txt" en la tabla mascota, usa este comando:

mysql> LOAD DATA LOCAL INFILE "mascota.txt" INTO TABLE mascota;

Puedes especificar el valor de separación de columna y el marcador de final de línea explícitamente
en la sentencia LOAD DATA si lo deseas, pero por defecto equivalen a TAB y LF (intro). Estos valores
por defecto son suficientes para que la sentencia que lee el fichero "mascota.txt" funcione
correctamente.

Cuando quieras añadir nuevos registros uno a uno, la sentencia INSERT es muy útil. En su forma más
simple, ofreces valores para cada columna, en el orden en el que las columnas fueron listadas en la
sentencia CREATE TABLE. Supón que Diane consige un nuevo hamster llamado Puffball. Podrías añadir un
nuevo registro usando una sentencia INSERT como esta:

mysql> INSERT INTO mascota
    -> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);

Observa que los valores string y fecha se espefican encerrados entre comillas. Observa también que,
con INSERT, puedes insertar NULL directamente para representar un valor perdido. No usamos \N como
hacíamos con LOAD DATA.

De este ejemplo, deberías ser capaz de ver que hubiera dido mucho más costoso teclear todos los
datos necesarios en la tabla mascota con sentencias INSERT que hacerlo como lo hemos hecho con una
única sentencia LOAD DATA.


8.3.4 Extrayendo información de una tabla
===============================================


La sentencia SELECT se usa para recabar información de una tabla. La forma
general de la sentencia es:

SELECT qué_seleccionar
FROM de_qué_tabla
WHERE condiciones_a_satisfacer

qué_seleccionar indica qué es lo que quieres seleccionar. Puede ser una lista de
columnas, o * para indicar "todas las columnas". de_qué_tabla indica la tabla de
la que quieres extraer datos. La claúsula WHERE es opcional. Si está presente,
condiciones_a_satisfacer especifica las codiciones que las filas deben cumplir
para estar presentes en el resultado de la selección.

8.3.4.1 Seleccionando todos los datos
=======================================

La forma más simplede SELECT recoge toda la información de una tabla:

mysql> SELECT * FROM mascota;
+----------+-------------+-----------+------+------------+------------+
| nombre   | propietario | especie   | sexo | nacimiento | muerte     |
+----------+-------------+-----------+------+------------+------------+
| Bluffy   |  Harold     | gato      | f    | 1993-02-04 | NULL       |
| Claws    |  Gwen       | gato      | m    | 1994-03-17 | NULL       |
| Buffy    |  Harold     | perro     | f    | 1989-05-13 | NULL       |
| Fang     |  Benny      | perro     | m    | 1990-08-27 | NULL       |
| Bowser   |  Diane      | perro     | m    | 1998-08-31 | 1995-07-29 |
| Chirpy   |  Gwen       | pájaro    | f    | 1998-09-11 | NULL       |
| Whistler |  Gwen       | pájaro    | NULL | 1997-12-09 | NULL       |
| Slim     |  Benny      | serpiente | m    | 1996-04-29 | NULL       |
| Puffball |  Diane      | hamster   | f    | 1999-03-30 | NULL       |
+----------+-------------+-----------+------+------------+------------+

Esta forma de SELECT es útil si quieres revisar tu tabla al completo, por
ejemplo, tras haberla cargado con tu conjunto inicial de datos. Como suele
suceder, la salida ya muestra un error en tu fichero de datos: Bowser ¡parece
haber nacido tras su muerte! Consultando tus papeles originales sobre el
pedigree del perro, descubres que la fecha correcta de nacimiento es 1989, no
1998.

Existen al menos un par de maneras de arreglar esto:

* Edita el fichero "mascota.txt" para corregir el error, después vacía la tabla
  y vuelve a cargarla usando DELETE y LOAD DATA:

mysql> DELETE from mascota;
mysql> LOAD DATA LOCAL INFILE "mascota.txt" INTO TABLE mascota;

Sin embargo, si haces esto, debes re-escribir el registro para Puffball.

* Arreglar sólo el registro erróneo con la sentencia UPDATE:

mysql> UPDATE mascota SET nacimiento="1989-08-31" WHERE nombre="Bowser";

Como se muestra más arriba, es fácil recuperar el cuerpo de una data. Pero
típicamente no querrás hacer eso, en particular cuando la tabla sea muy
larga. Generalmente, estarás más interesado en responder a una pregunta en
particular, en cuyo caso deberás especificar algunas restricciones en la
información que deseas. Veamos algunas consultas de selección en términos de
preguntas sobre tus mascotas que se deben responder.

8.3.4.2 Seleccionando filas en particular
=============================================

Puedes seleccionar sólo filas en particular de tu tabla. Por ejemplo, si quieres
verificar el cambio que has realizado a la fecha de nacimiento de Bowser,
selecciona el registro de Bowser de la siguiente forma:

mysql> SELECT * FROM mascota WHERE nombre="Bowser";
+--------+-------------+---------+------+------------+------------+
| nombre | propietario | especie | sexo | nacimiento | muerte     |
+--------+-------------+---------+------+------------+------------+
| Bowser |  Diane      | perro   | m    | 1989-08-31 | 1995-07-29 |
+--------+-------------+---------+------+------------+------------+

La salida confirma que el año está correctamente registrado como 1989, no 1998.

Las comparaciones de cadenas de texto son normalmente insensibles a las
mayúsculas/minúsculas, por lo que puedes especificar el nombre como "bowser",
"BOWSER", etc. El resultado de la consulta será el mismo.

Puedes especificar condiciones en cualquier columna, no sólo el nombre. Por
ejemplo, si quisieras saber qué animales nacieron a partir de 1998, examina la
columna nacimiento:

mysql> SELECT * FROM mascota WHERE nacimiento >= "1998-1-1";
+----------+-------------+---------+------+------------+--------+
| nombre   | propietario | especie | sexo | nacimiento | muerte |
+----------+-------------+---------+------+------------+--------+
| Chirpy   |  Gwen       | pájaro  | f    | 1998-09-11 | NULL   |
| Puffball | Diane       | hamster | f    | 1999-03-30 | NULL   |
+----------+-------------+---------+------+------------+--------+

Puedes combinar condiciones, por ejemplo, para localizar los perros hembra:

mysql> SELECT * FROM mascota WHERE especie="perro" AND sexo="f";
+--------+-------------+---------+------+------------+--------+
| nombre | propietario | especie | sexo | nacimiento | muerte |
+--------+-------------+---------+------+------------+--------+
| Buffy  |  Harold     | perro   | f    | 1989-05-13 | NULL   |
+--------+-------------+---------+------+------------+--------+

La consulta anterior usa el operador lógico AND. Existe también un operador OR:

mysql> SELECT * FROM mascota WHERE especie="serpiente" OR especie="pájaro";
+----------+-------------+-----------+------+------------+--------+
| nombre   | propietario | especie   | sexo | nacimiento | muerte |
+----------+-------------+-----------+------+------------+--------+
| Chirpy   |  Gwen       | pájaro    | f    | 1998-09-11 | NULL   |
| Whistler |  Gwen       | pájaro    | NULL | 1997-12-09 | NULL   |
| Slim     |  Benny      | serpiente | m    | 1996-04-29 | NULL   |
+----------+-------------+-----------+------+------------+--------+

AND y OR pueden entremezclarse. Si lo haces, es una buena idea el utilizar
paréntesis para indicar cómo deberían agruparse las condiciones:

mysql> SELECT * FROM mascota WHERE (especie="gato" AND sexo="m") 
    -> OR (especie="perro" AND sexo="f");
+--------+-------------+---------+------+------------+--------+
| nombre | propietario | especie | sexo | nacimiento | muerte |
+--------+-------------+---------+------+------------+--------+
| Claws  |  Gwen       | gato    | m    | 1994-03-17 | NULL   |
| Buffy  |  Harold     | perro   | f    | 1989-05-13 | NULL   |
+--------+-------------+---------+------+------------+--------+

8.3.4.3 Seleccionando columnas en particular
===================================================

Si no quieres ver filas completas de tu tabla, simplemente nombra las columnas
en las cuales estás interesado, separadas por comas. Por ejemplo, si quieres
saber cuándo nacieron tus animales, selecciona las columnas nombre y nacimiento:

mysql> SELECT nombre, nacimiento FROM mascota;
+----------+------------+
| nombre   | nacimiento |
+----------+------------+
| Bluffy   | 1993-02-04 |
| Claws    | 1994-03-17 |
| Buffy    | 1989-05-13 |
| Fang     | 1990-08-27 |
| Bowser   | 1989-08-31 |
| Chirpy   | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim     | 1996-04-29 |
| Puffball | 1999-03-30 |
+----------+------------+

Para averiguar quién posee mascotas, usa esta consulta:

mysql> SELECT propietario FROM mascota;                         
+-------------+
| propietario |
+-------------+
|  Harold     |
|  Gwen       |
|  Harold     |
|  Benny      |
|  Diane      |
|  Gwen       |
|  Gwen       |
|  Benny      |
|  Diane      |
+-------------+

Sin embargo, observa que la consulta simplemente obtiene el campo propietario de
cada registro, y algunos de ellos aparecen más de una vez. Para minimizar la
salida, obtén cada registro de salida único una sola vez añadiendo la palabra
reservada DISTINCT:

mysql> SELECT DISTINCT propietario FROM mascota;
+-------------+
| propietario |
+-------------+
|  Benny      |
|  Diane      |
|  Gwen       |
|  Harold     |
+-------------+

Puedes usar una claúsula WHERE para combinar la selección de filas con la
selección de columnas. Por ejemplo, para conseguir sólo las fechas de nacimiento
de perros y gatos, usa esta consulta:

mysql> SELECT nombre, especie, nacimiento FROM mascota
    -> WHERE especie = "perro" OR especie = "gato";
+--------+---------+------------+
| nombre | especie | nacimiento |
+--------+---------+------------+
| Bluffy | gato    | 1993-02-04 |
| Claws  | gato    | 1994-03-17 |
| Buffy  | perro   | 1989-05-13 |
| Fang   | perro   | 1990-08-27 |
| Bowser | perro   | 1989-08-31 |
+--------+---------+------------+

8.3.4.4 Ordenando filas
===========================

Tal vez hayas observado que en los ejemplos anteriores las filas del resultado
se muestran sin ningún tipo de orden en particular. Sin embargo, a menudo es más
fácil de examinar la salida de una consulta cuando las filas están ordenadas de
alguna manera en particular. Para ordenar un resultado, usa la claúsula ORDER
BY.

Aquí mostramos las fechas de nacimiento de los animales, ordenadas por fecha:

mysql> SELECT nombre, nacimiento FROM mascota ORDER BY nacimiento;
+----------+------------+
| nombre   | nacimiento |
+----------+------------+
| Buffy    | 1989-05-13 |
| Bowser   | 1989-08-31 |
| Fang     | 1990-08-27 |
| Bluffy   | 1993-02-04 |
| Claws    | 1994-03-17 |
| Slim     | 1996-04-29 |
| Whistler | 1997-12-09 |
| Chirpy   | 1998-09-11 |
| Puffball | 1999-03-30 |
+----------+------------+

Para ordenar de forma inversa, añade la palabra reservada DESC (descendente) al
nombre de la columna por la que estás ordenando:

mysql> SELECT nombre, nacimiento FROM mascota ORDER BY nacimiento DESC;
+----------+------------+
| nombre   | nacimiento |
+----------+------------+
| Puffball | 1999-03-30 |
| Chirpy   | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim     | 1996-04-29 |
| Claws    | 1994-03-17 |
| Bluffy   | 1993-02-04 |
| Fang     | 1990-08-27 |
| Bowser   | 1989-08-31 |
| Buffy    | 1989-05-13 |
+----------+------------+

Puedes ordenar por múltiples columnas. Por ejemplo, para ordenar por tipo de
animal, después por fecha de nacimiento dentro del mismo tipo de animal estando
los animales más jóvenes primero, usa la siguiente consulta:

mysql> SELECT nombre, especie, nacimiento FROM mascota ORDER BY especie, nacimiento DESC;
+----------+-----------+------------+
| nombre   | especie   | nacimiento |
+----------+-----------+------------+
| Claws    | gato      | 1994-03-17 |
| Bluffy   | gato      | 1993-02-04 |
| Puffball | hamster   | 1999-03-30 |
| Chirpy   | pájaro    | 1998-09-11 |
| Whistler | pájaro    | 1997-12-09 |
| Fang     | perro     | 1990-08-27 |
| Bowser   | perro     | 1989-08-31 |
| Buffy    | perro     | 1989-05-13 |
| Slim     | serpiente | 1996-04-29 |
+----------+-----------+------------+

Observa que la palabra reservada DESC se aplica sólo al nombre de columna que
preceda a la palabra reservada (nacimiento); los valores especie siguen siendo
ordenados en forma ascendente.

8.3.4.5 Cálculos de fecha
============================

MySQL ofrece muchas funciones que puedes usar para realizar cálculos con fechas,
por ejemplo, para calcular edades o extraer partes de fechas.

Para determinar cuantos años tiene cada una de tus mascotas, puedes calcular la
edad como la diferencia entre la fecha de nacimiento y la fecha actual. Puedes
hacerlo convirtiendo las dos fechas a dias, coge la diferencia, y divídela por
365 (el número de dias en un año):

mysql> select nombre, (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 FROM mascota;
+----------+------------------------------------------+
| nombre   | (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 |
+----------+------------------------------------------+
| Bluffy   |                                     6.94 |
| Claws    |                                     5.83 |
| Buffy    |                                    10.68 |
| Fang     |                                     9.39 |
| Bowser   |                                    10.38 |
| Chirpy   |                                     1.34 |
| Whistler |                                     2.10 |
| Slim     |                                     3.71 |
| Puffball |                                     0.79 |
+----------+------------------------------------------+

Aunque la consulta funcione, existen algunos puntos que podrían ser
mejorados. Primero, el resultado podría ser revisado más fácilmente si las filas
se presentaran ordenadas de alguna manera. Segundo, la cabecera de la columna
edad no es muy significativa.

El primer problema puede ser solucionado añadiendo una cláusula ORDER BY nombre
para ordenar la salida por nombre. Para arreglar el tema del encabezamiento de
columna, puedes darle un nombre a dicha columna de tal forma que aparezca una
etiqueta diferente en la salida (esto es lo que se llama un alias de columna):

mysql> select nombre, (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 AS edad         
    -> FROM mascota ORDER BY nombre;
+----------+-------+
| nombre   | edad  |
+----------+-------+
| Bluffy   |  6.94 |
| Bowser   | 10.38 |
| Buffy    | 10.68 |
| Chirpy   |  1.34 |
| Claws    |  5.83 |
| Fang     |  9.39 |
| Puffball |  0.79 |
| Slim     |  3.71 |
| Whistler |  2.10 |
+----------+-------+

Para ordenar la salida por edad en lugar de por nombre, puedes hacerlo usando
símplemente una cláusula ORDER BY diferente:

mysql> select nombre, (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 AS edad
    -> FROM mascota ORDER BY edad;
+----------+-------+
| nombre   | edad  |
+----------+-------+
| Puffball |  0.79 |
| Chirpy   |  1.34 |
| Whistler |  2.10 |
| Slim     |  3.71 |
| Claws    |  5.83 |
| Bluffy   |  6.94 |
| Fang     |  9.39 |
| Bowser   | 10.38 |
| Buffy    | 10.68 |
+----------+-------+

Puede usarse una consulta similar para determinar la edad de la muerte para los
animales que hayan muerto. Puedes determinar qué animales son estos comprobando
si el valor muerte es NULL o no. Después, para aquellos que no tengan un valor
NULL, calcular la diferencia entre los valores muerte y nacimiento:

mysql> select nombre, nacimiento, muerte,
    -> (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 AS edad
    -> FROM mascota WHERE muerte IS NOT NULL ORDER BY edad;
+--------+------------+------------+-------+
| nombre | nacimiento | muerte     | edad  |
+--------+------------+------------+-------+
| Bowser | 1989-08-31 | 1995-07-29 | 10.38 |
+--------+------------+------------+-------+

La consulta usa muerte IS NOT NULL en lugar de muerte != NULL dado que NULL es
un valor especial. Esto se explica más adelante. [Puedes consultar la sección
[Working with NULL] del manual de MySQL.

¿Qué harías si quisieras saber qué animales cumplen años el mes que viene? Para
este tipo de cálculos, año y día son irrelevantes, simplemente querrás extraer
la parte mes de la columna nacimiento. MySQL ofrece muchas funciones de
extracción de parte-de-fecha, como YEAR(),MONTH() y DAY(). La función apropiada
para nuestro problema es MONTH(). Para ver cómo funciona, ejecuta una consulta
rápida que muestre el valor de la fecha de nacimiento y el mes de nacimiento
(MONTH(nacimiento)):

mysql> SELECT nombre, nacimiento, MONTH(nacimiento) FROM mascota;
+----------+------------+-------------------+
| nombre   | nacimiento | MONTH(nacimiento) |
+----------+------------+-------------------+
| Bluffy   | 1993-02-04 |                 2 |
| Claws    | 1994-03-17 |                 3 |
| Buffy    | 1989-05-13 |                 5 |
| Fang     | 1990-08-27 |                 8 |
| Bowser   | 1989-08-31 |                 8 |
| Chirpy   | 1998-09-11 |                 9 |
| Whistler | 1997-12-09 |                12 |
| Slim     | 1996-04-29 |                 4 |
| Puffball | 1999-03-30 |                 3 |
+----------+------------+-------------------+

Buscar animales que hayan nacido en el mes próximo es también sencillo de
realizar. Suponte que Abril es el mes actual. Entonces el valor del mes es 4 y
lo que buscas son animales nacidos en Mayo (mes 5):

mysql> SELECT nombre, nacimiento FROM mascota WHERE MONTH(nacimiento) = 5;
+--------+------------+
| nombre | nacimiento |
+--------+------------+
| Buffy  | 1989-05-13 |
+--------+------------+

Existe una pequeña complicación si el mes actual es Diciembre, por supuesto. No
puedes añadir simplemente uno al número de mes (12) y buscar animales nacidos en
el mes 13, dado que no existe tal mes. En lugar de eso, debes buscar animales
nacidos en Enero (mes 1).

Puedes escribir la consulta de tal forma que funcione independientemente del mes
en el que estemos. De esa forma no tendrás que usar un número de mes en
particular en la consulta. DATE_ADD() te permite añadir un intervalo de tiempo a
una fecha dada. Si añades un mes al valor de NOW(), y después extraes la parte
del mes con MONTH(), el resultado produce el mes del cumpleaños que buscamos:


mysql> select NOW();
+---------------------+
| NOW()               |
+---------------------+
| 2000-01-13 18:13:09 |
+---------------------+

mysql> SELECT nombre, nacimiento FROM mascota
    -> WHERE MONTH(nacimiento) = MONTH(DATE_ADD(NOW(),INTERVAL 1 MONTH));
+--------+------------+
| nombre | nacimiento |
+--------+------------+
| Bluffy | 1993-02-04 |
+--------+------------+

Una manera difente de conseguir los mismos resultados es añadir 1 al mes actual
para conseguir el mes siguiente (tras usar la función módulo (MOD) para
convertir el valor de mes actual en 0 si estamos en Diciembre (mes 12)):

mysql> SELECT nombre, nacimiento FROM mascota
    -> WHERE MONTH(nacimiento) = MOD(MONTH(NOW()),12) +1;
+--------+------------+
| nombre | nacimiento |
+--------+------------+
| Bluffy | 1993-02-04 |
+--------+------------+


8.3.4.6 Trabajando con valores NULL
=======================================

Los valores NULL pueden ser sorprenderte hasta que te acostumbras a
usarlos. Conceptualmente, NULL significa "valor perdido" o "valor desconocido" y
se trata de forma diferente que otros valores. Para realizar comparaciones
respecto a NULL, no puedes utilizar los operadores de comparación aritméticos
como =, < o != . Puedes realizar una demostración de esto, prueba la siguiente consulta:

mysql> SELECT 1 = NULL, 1 != NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 != NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
|     NULL |      NULL |     NULL |     NULL |
+----------+-----------+----------+----------+

Ciertamente, de estas comparaciones no se pueden extraer resultados
significativos. Para conseguirlo, usa los operadores IS NULL y IS NOT NULL:

mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
+-----------+---------------+
| 1 IS NULL | 1 IS NOT NULL |
+-----------+---------------+
|         0 |             1 |
+-----------+---------------+

En MySQL, 0 significa falso y 1 significa VERDADERO.

Este tratamiento especial de NULL fue la causa de que en la sección anterior
fuera necesario determinar qué animales ya no vivían usando "muerte IS NOT NULL"
en lugar de "muerte != NULL".

8.3.4.7 Asociación/Coincidencia de patrones (PATTERN MATCHING)
================================================================

MySQL ofrece las características de asociación de patrones estándar así como
una forma de coincidencia de patrones basadas en expresiones regulares
extendidas similares a las usadas por utilidades UNIX como vi, grep y sed.

La asociación de patrones SQL te permite usar '_' para asociar cualquier
caracter simple, y '%' para asociar un número arbitrario de caracteres
(incluyendo cero caracteres). Los patrones SQL no toman en cuenta las
diferencias entre mayúsculas y minúsculas. Se muestran debajo algunos
ejemplos. Observa que no se utiliza = o != en el trabajo con patrones SQL; 
utiliza en su lugar los operadores de comparación LIKE o NOT LIKE.

Para buscar nombres que comienzan por "b":

mysql> SELECT * FROM mascota WHERE nombre LIKE "b%";
+--------+-------------+---------+------+------------+------------+
| nombre | propietario | especie | sexo | nacimiento | muerte     |
+--------+-------------+---------+------+------------+------------+
| Bluffy |  Harold     | gato    | f    | 1993-02-04 | NULL       |
| Buffy  |  Harold     | perro   | f    | 1989-05-13 | NULL       |
| Bowser |  Diane      | perro   | m    | 1989-08-31 | 1995-07-29 |
+--------+-------------+---------+------+------------+------------+

Para buscar nombres que terminen por "fy":

mysql> SELECT * FROM mascota WHERE nombre LIKE "%fy";
+--------+-------------+---------+------+------------+--------+
| nombre | propietario | especie | sexo | nacimiento | muerte |
+--------+-------------+---------+------+------------+--------+
| Bluffy |  Harold     | gato    | f    | 1993-02-04 | NULL   |
| Buffy  |  Harold     | perro   | f    | 1989-05-13 | NULL   |
+--------+-------------+---------+------+------------+--------+

Para buscar nombres que contengan una "w":

mysql> SELECT * FROM mascota WHERE nombre LIKE "%w%";
+----------+-------------+---------+------+------------+------------+
| nombre   | propietario | especie | sexo | nacimiento | muerte     |
+----------+-------------+---------+------+------------+------------+
| Claws    |  Gwen       | gato    | m    | 1994-03-17 | NULL       |
| Bowser   |  Diane      | perro   | m    | 1989-08-31 | 1995-07-29 |
| Whistler |  Gwen       | pájaro  | NULL | 1997-12-09 | NULL       |
+----------+-------------+---------+------+------------+------------+

Para buscar nombres de longitud cinco caracteres, usa el patrón "_" :

mysql> SELECT * FROM mascota WHERE nombre LIKE "_____";
+--------+-------------+---------+------+------------+--------+
| nombre | propietario | especie | sexo | nacimiento | muerte |
+--------+-------------+---------+------+------------+--------+
| Claws  |  Gwen       | gato    | m    | 1994-03-17 | NULL   |
| Buffy  |  Harold     | perro   | f    | 1989-05-13 | NULL   |
+--------+-------------+---------+------+------------+--------+

El otro tipo de asociación de patrones ofrecido por MySQL utiliza expresiones
regulares extendidas. Cuando se realiza una comprobación buscando una coincidencia
para este tipo de patrón, se deben usar los operadores REGEXP y NOT REGEXP (o
RLIKE y NOT RLIKE, dado que son sinónimos).

Algunas características de las expresiones regulares extendidas son:

* `.' se asocia con cualquier caracter (pero sólo uno)

* Una clase de caracteres `[...]' se asocia con culquier caracter contenido
  dentro de los corchetes. Por ejemplo, `[abc]' se asocia con 'a', 'b' ó

* 'c'. Para nombrar un rango de caracteres, usa un guión. `[a-z]' se asocia con
cualquier letra en minúscula, donde '[0-9]' se asocia con cualquier dígito.

* '*' se asocia con 0 o más instancias de lo que preceda al asterisco. Por
  ejemplo,'a*' coincide con cualquier número de a's,'[0-9]*' se asocia con
  cualquier número de dígitos, y '.*' se asocia con cualquier cosa.

* Las expresiones regulares son sensibles a las mayúsculas/minúsculas, pero
  puedes utilizar una clase caracter para asociar ambos casos si los deseas. Por
  ejemplo, '[aA]' coincide tanto con la letra a minúscula como con la letra A
  mayúscula y '[a-zA-Z]' coincide con cualquier letra en cualquier modo
  mayúscula/minúscula.

* El patrón se asocia si ocurre en cualquier lugar dentro del valor a ser
  probado (los patrones SQL coinciden sólo si se asocian con el valor
  completo). 

* Para anclar un patrón de manera que se busque la coincidencia bien al comienzo
  o bien al final del valor a ser comprobado, usa '^' al comienzo del patrón o
  '$' al final del patrón, respectivamente.

Para demostrar cómo funcionan las expresiones regulares, las consultas LIKE
mostradas antes son reescritas debajo para usar REGEXP:

Para buscar nombres que comiencen por "b", usa '^' para buscar la coincidencia
al comienzo del nombre y '[bB]' para buscar la asociación tanto con la b
minúscula como con la b mayúscula:

mysql> SELECT * FROM mascota WHERE nombre REGEXP "^[bB]";
+--------+-------------+---------+------+------------+------------+
| nombre | propietario | especie | sexo | nacimiento | muerte     |
+--------+-------------+---------+------+------------+------------+
| Bluffy |  Harold     | gato    | f    | 1993-02-04 | NULL       |
| Buffy  |  Harold     | perro   | f    | 1989-05-13 | NULL       |
| Bowser |  Diane      | perro   | m    | 1989-08-31 | 1995-07-29 |
+--------+-------------+---------+------+------------+------------+

Para buscar nombres que terminen por "fy", usa "$" para buscar la coincidencia
al final del nombre:

mysql> SELECT * FROM mascota WHERE nombre REGEXP "fy$";
+--------+-------------+---------+------+------------+--------+
| nombre | propietario | especie | sexo | nacimiento | muerte |
+--------+-------------+---------+------+------------+--------+
| Bluffy |  Harold     | gato    | f    | 1993-02-04 | NULL   |
| Buffy  |  Harold     | perro   | f    | 1989-05-13 | NULL   |
+--------+-------------+---------+------+------------+--------+

Para buscar nombres que contengan una "w", utiliza "[wW]" para buscar la
asociación tanto en mayúsculas como minúsculas:

 mysql> SELECT * FROM mascota WHERE nombre REGEXP "[wW]";
+----------+-------------+---------+------+------------+------------+
| nombre   | propietario | especie | sexo | nacimiento | muerte     |
+----------+-------------+---------+------+------------+------------+
| Claws    |  Gwen       | gato    | m    | 1994-03-17 | NULL       |
| Bowser   |  Diane      | perro   | m    | 1989-08-31 | 1995-07-29 |
| Whistler |  Gwen       | pájaro  | NULL | 1997-12-09 | NULL       |
+----------+-------------+---------+------+------------+------------+

Dado que un patrón de una expresión regular se asocia si ocurre en cualquier
lugar del valor, no es necesario poner un caracter comodín en ningún lado del
patrón para conseguir que se asocie con el valor completo como harías si usaras
un patrón SQL.

Para buscar nombres conteniendo exactamente cinco caracteres, usa "^" y "$" para
asociar el comienzo y el final de un nombre, y cinco instancias de "." entre
ellos:

mysql> SELECT * FROM mascota WHERE nombre REGEXP "^.....$";
+--------+-------------+---------+------+------------+--------+
| nombre | propietario | especie | sexo | nacimiento | muerte |
+--------+-------------+---------+------+------------+--------+
| Claws  |  Gwen       | gato    | m    | 1994-03-17 | NULL   |
| Buffy  |  Harold     | perro   | f    | 1989-05-13 | NULL   |
+--------+-------------+---------+------+------------+--------+

También podrías haber escrito la consulta anterior usando el operador '{n}'
"repetir n veces":

mysql> SELECT * FROM mascota WHERE nombre REGEXP "^.{5}$";
+--------+-------------+---------+------+------------+--------+
| nombre | propietario | especie | sexo | nacimiento | muerte |
+--------+-------------+---------+------+------------+--------+
| Claws  |  Gwen       | gato    | m    | 1994-03-17 | NULL   |
| Buffy  |  Harold     | perro   | f    | 1989-05-13 | NULL   |
+--------+-------------+---------+------+------------+--------+


8.3.4.8 Contando filas
=======================

Las bases de datos son usadas a menudo para responder a la pregunta, "¿cuantas
veces aparece un determinado tipo de datos en una tabla?". Por ejemplo, podrías
querer saber cuántas mascotas tienes, o cuántas mascotas tiene cada propietario,
o podrías querer realizar varios tipos de censos respecto a tus animales.

Contar el número total de animales que tienes es lo mismo que preguntar
"¿cuántas filas hay en la tabla mascota?", dado que hay sólo una fila por
mascota. La función COUNT() cuenta el número de resultados no-NULL , así pues, 
la consulta a realizar para contar el número de animales tiene la siguiente forma:

mysql> SELECT COUNT(*) FROM mascota;
+----------+
| COUNT(*) |
+----------+
|        9 |
+----------+

Antes, conseguiste los nombres de las personas que poseen una mascota. Puedes
usar COUNT() para averiguar cuántas mascotas tiene cada propietario:

mysql> SELECT propietario, COUNT(*) FROM mascota GROUP BY propietario;
+-------------+----------+
| propietario | COUNT(*) |
+-------------+----------+
|  Benny      |        2 |
|  Diane      |        2 |
|  Gwen       |        3 |
|  Harold     |        2 |
+-------------+----------+

Observa el uso de GROUP BY para agrupar todos los registros de cada
propietario. Si no lo hubiéramos puesto, todo lo que conseguirias sería un
mensaje de error:

mysql> SELECT propietario, COUNT(propietario) FROM mascota;
ERROR 1140: Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP
columns is illegal if there is no GROUP BY clause

COUNT() y GROUP BY son útiles para la caracterización de tus datos de varias
formas. Los siguientes ejemplos muestran difentes maneras para realizar
operaciones de censo animal.

Número de animales por especies:

mysql> SELECT especie, COUNT(*) FROM mascota GROUP BY especie;
+-----------+----------+
| especie   | COUNT(*) |
+-----------+----------+
| gato      |        2 |
| hamster   |        1 |
| pájaro    |        2 |
| perro     |        3 |
| serpiente |        1 |
+-----------+----------+

Número de animales por sexo:

mysql> SELECT sexo , COUNT(*) FROM mascota GROUP BY sexo;
+------+----------+
| sexo | COUNT(*) |
+------+----------+
| NULL |        1 |
| f    |        4 |
| m    |        4 |
+------+----------+

(En este resultado, NULL indica "sexo desconocido")

El número de animales por combinación de especies y sexo:

mysql> SELECT especie , sexo, COUNT(*) FROM mascota GROUP BY especie, sexo;
+-----------+------+----------+
| especie   | sexo | COUNT(*) |
+-----------+------+----------+
| gato      | f    |        1 |
| gato      | m    |        1 |
| hamster   | f    |        1 |
| pájaro    | NULL |        1 |
| pájaro    | f    |        1 |
| perro     | f    |        1 |
| perro     | m    |        2 |
| serpiente | m    |        1 |
+-----------+------+----------+

No necesitas recuperar una tabla completa cuando uses COUNT(). Por ejemplo, la
consulta anterior, cuando se realiza sólo sobre perros y gatos, se escribe así:

mysql> SELECT especie , sexo, COUNT(*) FROM mascota                        
    -> WHERE especie = "perro" OR especie = "gato"
    -> GROUP BY especie, sexo;
+---------+------+----------+
| especie | sexo | COUNT(*) |
+---------+------+----------+
| gato    | f    |        1 |
| gato    | m    |        1 |
| perro   | f    |        1 |
| perro   | m    |        2 |
+---------+------+----------+

O, si quieres conocer el número de animales por sexo sólo para animales de sexo
conocido:

mysql> SELECT especie , sexo, COUNT(*) FROM mascota
    -> WHERE sexo IS NOT NULL                     
    -> GROUP BY especie, sexo;
+-----------+------+----------+
| especie   | sexo | COUNT(*) |
+-----------+------+----------+
| gato      | f    |        1 |
| gato      | m    |        1 |
| hamster   | f    |        1 |
| pájaro    | f    |        1 |
| perro     | f    |        1 |
| perro     | m    |        2 |
| serpiente | m    |        1 |
+-----------+------+----------+


8.3.5 Usando más de una tabla
===============================

La tabla mascota guarda datos sobre las mascotas que posees. Si quieres guardar
otra información sobre ellos, como eventos en sus vidas, visitas al veterinario
o cuándo han tenido hermanos, necesitas otra tabla. ¿Cómo debería ser esta otra
tabla?

* Deberá contener el nombre de la mascota de tal forma que pudieras saber a qué
  animal corresponde cada evento almacenado en la misma.

* Necesitará una fecha para conocer cuándo ocurrió el evento.

* Necesitará un campo para describir el evento

* Si quieres ser capaz de categorizar los eventos, sería útil tener un campo de
  tipo evento.

Dadas estas consideraciones, la sentencia CREATE TABLE para la tabla "evento" se
parecería a esto:

mysql> CREATE TABLE evento (nombre VARCHAR(20), fecha DATE,
    -> tipo VARCHAR(15), anotación VARCHAR(255));

Como ocurría con la tabla mascota, es más fácil cargar los registros iniciales
creando un fichero de texto delimitado por tabuladores conteniendo la
información:

Fluffy		1995-05-15	parto		4 cachorros, 3 hembras, 1 macho
Buffy		1993-06-23	parto		5 cachorros, 2 hembras, 3 machos
Buffy		1994-06-19	parto		3 cachorros, 3 hembras
Chirpy		1999-03-21	veterinario	necesitó enderezamiento de pico
Slim		1997-08-03	veterinario	costilla rota
Bowser		1991-10-12	perrera
Fang		1991-10-12	perrera	
Fang		1998-08-28	cumpleaños	Se le regala un nuevo juguete de goma
Claws		1998-03-17	cumpleaños	Se le regala un nuevo collar de pulgas
Whistler	1998-12-09	cumpleaños	Primer cumpleaños


Carga los registros así:

mysql> LOAD DATA LOCAL INFILE "evento.txt" INTO TABLE evento;

Basándote en lo que has aprendido de las consultas que has ejecutado em la tabla
mascota, deberías ser capaz de realizar recuperaciones de datos en los registros
de la tabla "evento"; los principios son los mismos. ¿Pero qué hacer cuando la
tabla evento no sea suficiente por sí sola de responder a cuestiones que
podrías llegar a realizar?

Supón que quisieras averiguar las edades de cada mascota al tener cachorros. La
tabla evento indica cuándo ha ocurrido esto, pero para calcular la edad de la
madre, necesitas su fecha de nacimiento. Dado que eso está almacenado en la
tabla mascota, necesitas ambas tablas para la consulta:

mysql> SELECT mascota.nombre , (TO_DAYS(fecha) - TO_DAYS(nacimiento))/365 AS edad, anotación
    -> FROM mascota, evento
    -> WHERE mascota.nombre = evento.nombre AND tipo = "parto";
+--------+------+----------------------------------+
| nombre | edad | anotación                        |
+--------+------+----------------------------------+
| Fluffy | 2.27 | 4 cachorros, 3 hembras, 1 macho  |
| Buffy  | 4.12 | 5 cachorros, 2 hembras, 3 machos |
| Buffy  | 5.10 | 3 cachorros, 3 hembras           |
+--------+------+----------------------------------+

Existen varios puntos que anotar sobre esta consulta:

* La cláusula FROM lista dos tablas dado que la consulta necesita extraer
  información de las dos.

* Cuando se combina la información de múltiples tablas, necesitas especificar
  cómo pueden ser asociados los registros de una tabla con los registros de la
  otra. Esto es fácil dado que ambas tienen una columna nombre (N.T.: nombre es
  una clave extranjera). La consulta usa la cláusula WHERE para combinar los
  registros de las dos tablas basándose en los valores de nombre.

* Dado que la columna nombre aparece en ambas tablas, debes ser específico sobre
  a qué tabla te refieres cuando estés hablando de esa columna. Esto se realiza
  poniendo el nombre de la tabla como prefijo de la columna.

No necesitas tener dos tablas diferentes para realizar un join. En algunas 
ocasiones es útil realizar un join de una tabla consigo misma, si quieres comparar 
registros de una tabla con otros registros en la misma tabla. Por ejemplo, para buscar
parejas de sexos entre tus mascotas, puedes enlazar la tabla mascota consigo
mismo para emaparejar machos y hembras de las mismas especies:

mysql> SELECT p1.nombre, p1.sexo, p2.nombre, p2.sexo, p1.especie
    -> FROM mascota AS p1, mascota AS p2
    -> WHERE p1.especie = p2.especie AND p1.sexo = "f" AND p2.sexo = "m";
+--------+------+--------+------+---------+
| nombre | sexo | nombre | sexo | especie |
+--------+------+--------+------+---------+
| Fluffy | f    | Claws  | m    | gato    |
| Buffy  | f    | Fang   | m    | perro   |
| Buffy  | f    | Bowser | m    | perro   |
+--------+------+--------+------+---------+


En esta consulta, especificamos un par de alias para el nombre de las tablas
y ser capaces así de referirnos a las columnas y saber en todo momento a qué
instancia de qué tabla se asocia cada referencia de columna.

8.4 Obtener información sobre bases de datos y tablas
================================================================

¿Qué ocurre si olvidas el nombre de una base de datos o de una tabla, o cuál es
la estructura de una tabla dada (ejm. : ¿cómo se llaman sus columnas?) MySQL
soluciona este problema a través de numerosas sentencias que ofrecen información
sobre las bases de datos y las tablas que soporta.

Ya hemos visto SHOW DATABASES, que lista las bases de datos gestionadas por el
servidor. Para averiguar qué base de datos está actualmente seleccionada, usa la
función DATABASE():

mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| zoo        |
+------------+

Si aún no has seleccionado ninguna base de datos, el resultado estará en blanco.

Para averiguar qué tablas contiene la base de datos actual (por ejemplo, cuando
no estás seguro sobre el nombre de una tabla), usa este comando:

mysql> SHOW TABLES;
+---------------+
| Tables in zoo |
+---------------+
| evento        |
| mascota       |
+---------------+

Si quieres averiguar la estructura de una tabla, el comando DESCRIBE te será
útil; muestra información sobre cada columna de una tabla:

mysql> DESCRIBE mascota;
+-------------+-------------+------+-----+---------+-------+
| Field       | Type        | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| nombre      | varchar(20) | YES  |     | NULL    |       |
| propietario | varchar(20) | YES  |     | NULL    |       |
| especie     | varchar(20) | YES  |     | NULL    |       |
| sexo        | char(1)     | YES  |     | NULL    |       |
| nacimiento  | date        | YES  |     | NULL    |       |
| muerte      | date        | YES  |     | NULL    |       |
+-------------+-------------+------+-----+---------+-------+

Field indica el nombre de la columna, Type es el tipo de datos para la columna,
Null indica si la columna puede contener o no valores NULL, Key indica si la
columna está indexada o no, y Default especifica el valor por defecto para la
columna.

Si tienes índices en una tabla, SHOW INDEX FROM nombre_tabla te mostrará
información sobre ellos.

8.5 Usando mysql en modo batch 
=================================

En las secciones previas, hemos usado mysql interactivamente para introducir
consultas y observar los resultados. También puedes ejecutar mysql en modo
batch. Para realizarlo, escribe los comandos que quieras ejecutar en un fichero,
después pídele a mysql que lea su entrada desde el fichero:

shell> mysql < fichero-batch

(N.T.: en ocasiones se traduce como fichero por lotes)

Si necesitas especificar parámetros de conexión en la línea de comandos, el
comando podría parecerse a esto:

shell> mysql -h host -u user -p < fichero-batch
Enter password: ********

Cuando usas MySQL de esta manera, estás creando un fichero script (de guión), y
después ejecutando el script.

¿Por qué usar un script? He aquí algunas razones:

* Si ejecutas una consulta repetidamente (digamos, cada día o cada semana), el
  construir un script con esta consulta te permite evitar volver a teclearla
  cada vez que la ejecutes.

* Puedes generar nuevas consultas a partir de consultas ya existentes similares
  simplemente copiando y editando los ficheros script.

* El modo batch puede ser también muy útil cuando estés desarrollando una
  consulta, particularmente para comandos multi-línea o múltiples secuencias de
  comandos de múltiples sentencias. Si cometes un error, no necesitas reescribir
  todo. Símplemente edita el script para corregir el error, y después pídele a
  mysql que lo vuelva a ejecutar.

* Si tienes una consulta que produce resultados muy largos, puedes usar un
  paginador para filtrar esta salida en lugar de ver cómo se desplaza fuera del
  alcance de tu pantalla:


shell> mysql < fichero_batch | more

* Puedes redirigir la salida a un fichero para un procesamiento posterior:

shell> mysql < fichero_batch > mysql.out

* Puedes distribuir tu script a otras personas para que puedan ejecutar también
  tus comandos.

* Algunas situaciones no permiten un uso interactivo, por ejemplo, cuando
  ejecutas una consulta como una tarea de cron. (N.T.: cron es un comando UNIX
  que sirve para planificar y ejecutar comandos UNIX en el tiempo). En este
  caso, debes usar el procesamiento por lotes.

El formato de salida por defecto es diferente (más conciso) cuando ejecutas
mysql en modo batch que cuando lo usas de manera interactiva. Por ejemplo, la
salida de SELECT DISTINCT especie FROM mascota   es la siguiente cuando se
ejecuta de manera interactiva:

mysql> SELECT DISTINCT especie FROM mascota;
+-----------+
| especie   |
+-----------+
| gato      |
| hamster   |
| pájaro    |
| perro     |
| serpiente |
+-----------+

Y la siguiente si se ejecuta en modo batch:

especie
gato
hamster
pájaro
perro
serpiente

Si quieres obtener el formato de salida del modo interactivo también en modo
batch, usa mysql -t. Para redirigir a salida estándar los comandos que se están
ejecutando, usa mysql -vvv.



8.6 Consultas del proyecto gemelos

En Analytikerna y Lentus, hemos estado realizando el trabajo de campo y sistemas para
un gran proyecto de investigación. Este proyecto es una colaboración entre el Instituto de
Medicina Medioambiental en el Karolinska Institutet Stockholm y la Sección en Investigación
Clínica en Envejecimiento y Psicología en la Universidad del Sur de California.

El proyecto consistió en una parte de selección donde todos los gemelos en Suecia mayores de
65 años eran entrevistados por teléfono. Los gemelos que reunían ciertos criterios pasaban a la
siguiente fase. En esta fase posterior, los gemelos que querían participar eran visitados por
un equipo doctor/enfermera. Algunos de los exámenes incluían exámenes físicos y neuropsicológicos,
pruebas de laboratorio, neuroimágenes, valoración del estado psicológico, y recopilación de la
historia familiar. Además, se recogieron datos sobre los factores de riesgo médicos y
medioambientales.

Puede encontrarse más información sobre los estudios de gemelos en :

      http://www.imm.ki.se/TWIN/TWINUKW.HTM

La última parte del proyecto se administra con un interfaz web escrito usando Perl y MySQL.
Cada noche, todos los datos de las entrevistas son movidos a una base de datos MySQL.

8.6.1 Buscar todos los gemelos no-distribuidos

La siguiente consulta se usa para determinar quién pasa a la segunda parte del proyecto:

 select
             concat(p1.id, p1.tvab) + 0 as tvid,
             concat(p1.christian_name, " ", p1.surname) as Name,
             p1.postal_code as Code,
             p1.city as City,
             pg.abrev as Area,
             if(td.participation = "Aborted", "A", " ") as A,
             p1.dead as dead1,
             l.event as event1,
             td.suspect as tsuspect1,
             id.suspect as isuspect1,
             td.severe as tsevere1,
             id.severe as isevere1,
             p2.dead as dead2,
             l2.event as event2,
             h2.nurse as nurse2,
             h2.doctor as doctor2,
             td2.suspect as tsuspect2,
             id2.suspect as isuspect2,
             td2.severe as tsevere2,
             id2.severe as isevere2,
             l.finish_date
     from
             twin_project as tp
             /* For Twin 1 */
             left join twin_data as td on tp.id = td.id and tp.tvab = td.tvab
             left join informant_data as id on tp.id = id.id and tp.tvab = id.tvab
             left join harmony as h on tp.id = h.id and tp.tvab = h.tvab
             left join lentus as l on tp.id = l.id and tp.tvab = l.tvab
             /* For Twin 2 */
             left join twin_data as td2 on p2.id = td2.id and p2.tvab = td2.tvab             left join informant_data as id2 on p2.id = id2.id and p2.tvab = id2.tvab
             left join harmony as h2 on p2.id = h2.id and p2.tvab = h2.tvab
             left join lentus as l2 on p2.id = l2.id and p2.tvab = l2.tvab,
             person_data as p1,
             person_data as p2,
             postal_groups as pg
     where
             /* p1 gets main twin and p2 gets his/her twin. */
             /* ptvab is a field inverted from tvab */
             p1.id = tp.id and p1.tvab = tp.tvab and
             p2.id = p1.id and p2.ptvab = p1.tvab and
             /* Just the sceening survey */
             tp.survey_no = 5 and
             /* Skip if partner died before 65 but allow emigration (dead=9) */
             (p2.dead = 0 or p2.dead = 9 or
              (p2.dead = 1 and
               (p2.death_date = 0 or
                (((to_days(p2.death_date) - to_days(p2.birthday)) / 365)
                 >= 65))))
             and
             (
             /* Twin is suspect */
             (td.future_contact = 'Yes' and td.suspect = 2) or
             /* Twin is suspect - Informant is Blessed */
             (td.future_contact = 'Yes' and td.suspect = 1 and id.suspect = 1) o
             /* No twin - Informant is Blessed */
             (ISNULL(td.suspect) and id.suspect = 1 and id.future_contact = 'Yes') or
             /* Twin broken off - Informant is Blessed */
             (td.participation = 'Aborted'
              and id.suspect = 1 and id.future_contact = 'Yes') or
             /* Twin broken off - No inform - Have partner */
             (td.participation = 'Aborted' and ISNULL(id.suspect) and p2.dead = 0))
             and
             l.event = 'Finished'
             /* Get at area code */
             and substring(p1.postal_code, 1, 2) = pg.code
             /* Not already distributed */
             and (h.nurse is NULL or h.nurse=00 or h.doctor=00)
             /* Has not refused or been aborted */
             and not (h.status = 'Refused' or h.status = 'Aborted'
             or h.status = 'Died' or h.status = 'Other')
     order by
             tvid;

Algunas explicaciones:

`concat(p1.id, p1.tvab) + 0 as tvid'
     Queremos ordenar por la concatenación de `id' y `tvab' en orden numérico.
     Añadiendo `0' al resultado provocamos que *MySQL* trate el resultado como 
     un número.

column `id'
     Esto identifica un par de gemelos. Es una clave en todas las tablas.

column `tvab'
     Esto identifica un gemelo de una pareja. Tiene un valor de `1' ó `2'

column `ptvab'
     Esto es la inversa de `tvab'. Cuando `tvab' es `1' esto es `2', y
     vice versa. Esto existe para ahorrarnos teclear y para hacer más fácil
     la optimización de la consulta a MySQL. 


Esta consulta demuestra, entre otras cosas, cómo realizar búsquedas en una tabla
enlazada con la misma tabla a través de un join (p1 y p2). En el ejemplo, ésto
se usa para comprobar cuándo un gemelo de una pareja murió antes de cumplir 65. 
En caso afirmativo, la fila no es devuelta.

Todo lo anterior existe en todas las tablas con información relacionada con los gemelos.
Tenemos una clave tanto en id, tvab (todas las tablas) como en id,ptvab (person_data) para
construir consultas más rápidas.

En nuestra máquina de producción (una UltraSPARC 200MHz), esta consulta devuelve alrededor
de 150-200 filas y tarda menos de un segundo.

El número actual de registros en las tablas usadas arriba:

Tabla		    Filas

person_data          71074                                
lentus               5291                                 
twin_project         5286                                 
twin_data            2012                                 
informant_data       663                                  
harmony              381                                  
postal_groups        100     




8.6.2 Mostrar una tabla con el estado de la pareja de gemelos.

Cada entrevista finaliza con un código de estado llamado event. La consulta mostrada
debajo se usa para imprimir una tabla sobre todas las parejas de gemelos combinadas por evento.
Esto indica en cuántas parejas ambos gemelos han finalizado, en cuántas parejas
ha finalizado un gemelo y el otro se rechazó, etc.

  select
             t1.event,
             t2.event,
             count(*)
     from
             lentus as t1,
             lentus as t2,
             twin_project as tp
     where
             /* We are looking at one pair at a time */
             t1.id = tp.id
             and t1.tvab=tp.tvab
             and t1.id = t2.id
             /* Just the sceening survey */
             and tp.survey_no = 5
             /* This makes each pair only appear once */
             and t1.tvab='1' and t2.tvab='2'
     group by
             t1.event, t2.event;