Você está na página 1de 69

Apndice B

SOLUCIONES (Cuestionarios y Prcticas adicionales) CAPTULO 2: CONCEPTOS CLIENTE/SERVIDOR EN MYSQL. Cuestionario. 1. Todos los programas cliente y utilidades de MySQL se comunican con el servidor MySQL. (Verdadero o Falso) Falso. Hay utilidades de MySQL que no se comunican con el servidor, sino que actan directamente con las tablas MyISAM. Algunos ejemplos son myisamchk y myisampack. 2. Cuando un servidor MySQL se ejecuta en Windows, los programas cliente que acceden a ese servidor tienen que ejecutarse tambin en Windows. (Verdadero o Falso). Falso. MySQL se puede usar en entornos heterogneos. Por ejemplo, un servidor ejecutndose en una mquina UNIX puede ser accedido por clientes en mquinas Windows. 3. Un programa de lnea de comandos comnmente utilizado para comunicarse con el servidor se llama mysqld. (Verdadero o Falso). Falso. El programa de lnea de comandos ms usado se llama mysql, no mysqld. Este ltimo es el servidor MySQL. 4. Cada tabla tiene su propio archivo .frm (o de formato) que contiene una descripcin de la estructura de la tabla, ubicado en el directorio correspondiente de la base de datos. 5. El servidor ejecuta cada sentencia usando un modelo de procesamiento de dos niveles: El nivel superior incluye el analizador sintctico SQL y el optimizador. El nivel inferior consiste en un conjunto de motores de almacenamiento.

Apndice B

CAPTULO 3: LOS CLIENTES MYSQL. Cuestionario. 1. Dnde tiene que ser instalado el Connector/ODBC de MySQL? (a). El connector/ODBC tiene que ser instalado en todos los hosts de cliente donde se ejecutan programas que deberan usar ese conector.

2. Cul de las siguientes declaraciones es verdadera? (d). Los conectores de MySQL son entregados por separado de las distribuciones del servidor MySQL de Sun Microsystems, Inc. 3. El connector/NET de MySQL slo funciona en Windows (Verdadero o Falso). Falso. El conector/NET de MySQL funciona en cada plataforma que implemente el framework .NET. Aparte de Windows, incluye a los sistemas Linux con Mono instalado. 4. Todos los conectores de MySQL estn basados en API C de MySQL y estn implementados usando la librera de clientes C de MySQL (Verdadero o Falso). Falso. Los conectores Connector/NET y Connector/J son ejemplos de conectores que no usan las libreras C sino que implementan el protocolo cliente/servidor directamente. 5. Es verdadera la siguiente declaracin? Al igual que los dems programas MySQL, los conectores de MySQL estn escritos en C (Verdadero o Falso). Es falsa. Por ejemplo el Connector/NET de MySQL est escrito en C#, y el Connector/J de MySQL est escrito en Java.

Apndice B

CAPTULO 4: CONSULTANDO LOS DATOS DE LAS TABLAS. Prctica adicional. 1. Listar las diferentes regiones del mundo.

mysql> SELECT DISTINCT Region FROM Country; +---------------------------+ | Region |

+---------------------------+ | Caribbean |

| Southern and Central Asia | : | Micronesia/Caribbean : |

+---------------------------+ 25 rows in set (#.## sec)

2. Listar los primeros tres pases en orden alfabtico.

mysql> SELECT Name FROM Country ORDER BY Name LIMIT 3; +-------------+ | Name |

+-------------+ | Afghanistan | | Albania | Algeria | |

+-------------+ 3 rows in set (0.00 sec)

3. Listar todos los pases blticos, pertenecientes a la regin 'Baltic Countries'.

mysql> SELECT Name, Region FROM Country WHERE Region='Baltic Countries'; +-----------+------------------+ | Name | Region |

+-----------+------------------+ | Estonia | Baltic Countries |

| Lithuania | Baltic Countries | | Latvia | Baltic Countries |

+-----------+------------------+ 3 rows in set (0.01 sec)

Apndice B

4. Listar todos los pases donde la esperanza de vida es mayor de 79 aos.

mysql> SELECT Name, LifeExpectancy FROM Country -> WHERE LifeExpectancy > 79; +-------------+----------------+ | Name | LifeExpectancy |

+-------------+----------------+ | Andorra | Australia | Canada | | | 83.5 | 79.8 | 79.4 | 79.6 | 79.5 | 79.4 | 80.7 | 81.6 | 80.1 | 81.1 | 79.6 |

| Switzerland | | Hong Kong | Iceland | Japan | Macao | Singapore | San Marino | Sweden | | | | | | |

+-------------+----------------+ 11 rows in set (0.00 sec)

5. Listar las 5 ciudades ms grandes del mundo.

mysql> SELECT Name FROM City ORDER BY Population DESC LIMIT 5; +-----------------+ | Name |

+-----------------+ | Mumbai (Bombay) | | Seoul | So Paulo | Shanghai | Jakarta | | | |

+-----------------+ 5 rows in set (0.17 sec)

Apndice B

6. Listar los distintos pases (cdigos de pas) que tienen ciudades con ms de 7.000.000 de habitantes. Cuntos pases hay?

mysql> SELECT DISTINCT CountryCode FROM City WHERE Population > 7000000; +-------------+ | CountryCode | +-------------+ | BRA | GBR | IDN | IND | JPN | CHN | KOR | MEX | PAK | TUR | RUS | USA | | | | | | | | | | | |

+-------------+ 12 rows in set (0.00 sec)

7. Encontrar los cinco tipos de gobierno ms comunes en el mundo (entendiendo ms comunes como el que haya en mayor nmero de pases).

mysql> SELECT GovernmentForm, COUNT(*) FROM Country -> GROUP BY GovernmentForm ORDER BY COUNT(*) DESC LIMIT 5; +-------------------------------+----------+ | GovernmentForm | COUNT(*) |

+-------------------------------+----------+ | Republic | Constitutional Monarchy | Federal Republic | | | 122 | 29 | 15 | 12 | 5 |

| Dependent Territory of the UK | | Monarchy |

+-------------------------------+----------+ 5 rows in set (0.03 sec)

Apndice B

8. Listar la superficie promedio de los pases de cada continente.

mysql> SELECT Continent, AVG(SurfaceArea) AS AverageSurfaceArea -> FROM Country GROUP BY Continent; +---------------+--------------------+ | Continent | AverageSurfaceArea |

+---------------+--------------------+ | Asia | Europe | | 625117.745098 | 501068.128261 | 654445.135135 | 521558.224138 | 305867.642857 | 2626420.200000 | 1276066.142857 |

| North America | | Africa | Oceania | Antarctica | | |

| South America |

+---------------+--------------------+ 7 rows in set (0.00 sec)

9. Calcular la esperanza promedio de vida de cada continente (recordar que cada pas tiene distinta poblacin).

mysql> SELECT Continent, SUM(Population*LifeExpectancy)/SUM(Population) -> AS LifeExpectancy FROM Country GROUP BY Continent; +---------------+----------------+ | Continent | LifeExpectancy |

+---------------+----------------+ | Asia | Europe | | 67.35223 | 73.82361 | 74.91544 | 52.03168 | 75.90188 | NULL | 67.54434 |

| North America | | Africa | Oceania | Antarctica | | |

| South America |

+---------------+----------------+ 7 rows in set (0.03 sec)

Apndice B

10. Listar los 5 pases con mayor densidad de poblacin en el mundo (slo incluir pases con una superficie mayor que 10.000).

mysql> SELECT Name, Population/SurfaceArea AS PopulationDensity -> FROM Country WHERE SurfaceArea > 10000 -> ORDER BY PopulationDensity DESC LIMIT 5; +-------------+-------------------+ | Name | PopulationDensity |

+-------------+-------------------+ | Bangladesh | Taiwan | | 896.922179 | 615.010501 | 471.106463 | 382.025719 | 335.506914 |

| South Korea | | Netherlands | | Belgium |

+-------------+-------------------+ 5 rows in set (0.00 sec)

11. Cuntos distritos distintos hay representados en la tabla City?

mysql> SELECT COUNT(DISTINCT district) FROM City; +--------------------------+ | COUNT(DISTINCT district) | +--------------------------+ | 1351 |

+--------------------------+ 1 row in set (0.01 sec)

12. Listar todos los idiomas que se hablan en ms de 10 pases.

mysql> SELECT Language, COUNT(*) FROM CountryLanguage GROUP BY Language -> HAVING COUNT(*) > 10 ORDER BY COUNT(*) DESC; +----------------+----------+ | Language | COUNT(*) |

+----------------+----------+ | English | Arabic | Spanish | French | German | Chinese | Russian | Italian | | | | | | | | 60 | 33 | 28 | 25 | 19 | 19 | 17 | 15 | 14 | 12 |

| Creole English | | Portuguese |

Apndice B

| Ful | Turkish | Ukrainian

| | |

12 | 12 | 12 |

+----------------+----------+ 13 rows in set (0.16 sec)

CAPTULO 5: MANEJO DE ERRORES Y ALERTAS. Cuestionario. En este ejercicio se respondern preguntas relacionadas con los Modos SQL. 1. Cul de las siguientes declaraciones es verdadera? a) Falsa. Esta sentencia sera cierta solo en los casos en los que el modo SQL se establezca de forma global y para los clientes que se conecten despus de que el modo SQL haya sido establecido. b) Falso. Si se desea activar dos modos SQL (por ejemplo STRICT_ALL_TABLES y ERROR_FOR_DIVISION_BY_ZERO), se debe hacer en una sola sentencia, como sta:

SET sql_mode = 'STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';

c)

Verdadero. A menos que se declare explcitamente como global, los modos SQL slo afectan el cliente que da valor a los modos.

d)

Verdadero. Los modos SQL afectan el comportamiento del servidor; por ejemplo, influyen en cmo maneja el servidor los datos de entrada invlidos.

e)

Falso. Los modos SQL no afectan las caractersticas (funcionalidades) que el servidor brinda a un cliente; por ejemplo, solo puede activarse y desactivarse el soporte de InnoDB al iniciar el servidor.

2. Cul es la sintaxis para cambiar el modo SQL a 'STRICT_TRANS_TABLES' y 'PIPES_AS_CONCAT'?

SET sql_mode = 'STRICT_TRANS_TABLES,PIPES_AS_CONCAT';

Apndice B

3. Si se intenta guardar un valor negativo en una columna UNSIGNED, MySQL lo convierte al valor vlido ms cercano posible para esa columna. Cul es ese valor? El cero. 4. Qu tipo de valores se usar para la siguiente sentencia INSERT de columna?

mysql> INSERT INTO table1 VALUES();

Los valores por defecto. 5. En un determinado modo SQL, MySQL ajusta los valores de entrada invlidos a los valores legales cuando es posible y genera mensajes de alerta. El modo SQL puede tambin ajustarse a fin de enviar errores en vez de mensajes de alerta. Cul es el trmino general de modos SQL que activan un comportamiento menos permisivo? El modo estricto. 6. El Servidor MySQL genera alertas o errores cuando no es capaz de satisfacer completamente un requerimiento o cuando una accin tiene efectos colaterales no intencionados. Estas alertas y errores pueden ser desplegadas gracias a las siguientes dos sentencias: SHOW WARNINGS y SHOW ERRORS. 7. Listar los tres niveles de gravedad de las alertas: a) b) c) Error: mensajes que indican problemas serios que previenen al servidor de resolver una peticin. Warning: mensajes que indican problemas para los que el servidor puede continuar procesando la peticin. Nota: mensajes nicamente informativos.

Apndice B

Prctica adicional. 1. Encontrar las pginas en el manual de referencia que listan los cdigos de error (usar la versin ms actualizada del manual de referencia versin 5.1). http://dev.mysql.com/doc/refman/5.1/en/error-handling.html Mira los enlaces individuales de cdigos de errores del servidor y del cliente: http://dev.mysql.com/doc/refman/5.1/en/error-messages-server.html http://dev.mysql.com/doc/refman/5.1/en/error-messages-client.html 2. Usando perror, encontrar qu representa el cdigo de error 130.

shell> perror 130 MySQL error code 130: Incorrect file format

3.

Usando la base de datos test, intentar listar el contenido de todas las filas de una tabla llamada test_table. Qu tipo de mensaje se recibe?

mysql> use test Database changed

mysql> SELECT * FROM test_table; ERROR 1146 (42S02): Table 'test.test_table' doesn't exist

4.

Encontrar la descripcin exacta del cdigo de error en el manual de referencia en lnea para este tipo de error. Error: 1146 SQLSTATE: 42S02(ER_NO_SUCH_TABLE) Message: Table '%s.%s' doesn't exist

5.

Mostrar la actual definicin de modo SQL. Cambiar el modo SQL a ANSI. Confirmar que el modo ha sido cambiado.

mysql> SELECT @@SQL_MODE; +----------------------------------------------------------------+ | @@SQL_MODE |

+----------------------------------------------------------------+ | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | +----------------------------------------------------------------+ 1 row in set (0.00 sec)

Apndice B

mysql> SET SQL_MODE='ANSI'; Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@SQL_MODE; +-------------------------------------------------------------+ | @@SQL_MODE |

+-------------------------------------------------------------+ | REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI | +-------------------------------------------------------------+ 1 row in set (0.00 sec)

6.

Intentar eliminar la tabla test_table (Usar DROP TABLE IF EXISTS). Qu tipo de mensaje se recibe?

mysql> DROP TABLE IF EXISTS test_table; Query OK, 0 rows affected, 1 warning (0.00 sec)

7.

Usar la sentencia SHOW apropiada para ver una descripcin del mensaje.

mysql> SHOW WARNINGS; +-------+------+----------------------------+ | Level | Code | Message |

+-------+------+----------------------------+ | Note | 1051 | Unknown table 'test_table' |

+-------+------+----------------------------+ 1 row in set (0.02 sec)

8.

Ver los errores actuales. Explicar el resultado.

mysql> SHOW ERRORS; Empty set (0.00 sec)

Dado que el problema con DROP TABLE fue un aviso (warning) y no un error, este comando no mostrar ningn error.

Apndice B

CAPTULO 6: TIPOS DE DATOS. Cuestionario. 1. Si se quiere almacenar valores monetarios (por ejemplo, valores que representen dlares americanos y cntimos, como $48.99), qu tipo de datos se debe usar para evitar errores de redondeo? DECIMAL. 2. Qu tipo de datos es ms eficiente en trminos de espacio? CHAR(100) o VARCHAR(100)? CHAR(100) almacena 100 caracteres para cada registro, mientras que

VARCHAR(100) almacena slo el nmero de caracteres realmente insertado, ms un byte para almacenar la longitud de esa entrada. Esto significa que VARCHAR(100) es, normalmente, ms eficiente en cuanto a espacio se refiere. No obstante, en el caso especial en que se inserten valores de 100 caracteres en la columna, CHAR(100) sera ms eficiente, porque el byte usado por VARCHAR para almacenar la longitud de cada entrada, sera innecesario. 3. En una tabla population, se quiere guardar el nmero de habitantes de las ciudades. El espacio de almacenamiento es de mucha importancia. Se espera que la mxima poblacin que tendr una ciudad es de 15.000.000 habitantes. Qu tipo de datos (y atributos de columna deseados) se usaran? Cul es el requerimiento de espacio para este tipo de datos? MEDIUMINT UNSIGNED puede almacenar nmeros hasta 16.777.215. El atributo UNSIGNED asegura que no se almacenen nmeros negativos por accidente. Sin UNSIGNED, el valor mximo positivo podra ser solo 8.388.607. El espacio requerido es de 3 bytes por valor. 4. Se efecta la siguiente operacin de INSERT sobre la tabla datetest, con una sola columna DATE llamada d con valor de defecto NULL:

mysql> INSERT INTO datetest VALUES ('12:00:00');

Apndice B

Qu

valores

sern

almacenados

realmente

en

la

tabla?

Explique

brevemente. La respuesta depende del modo SQL del servidor en el que se ejecuta. Si el modo SQL es TRADITIONAL, ocurrir un error:

mysql> INSERT INTO datetest VALUES ('12:00:00'); ERROR 1292 (22007): Incorrect date value: '12:00:00' for column 'd' at row 1

Esto ocurre porque el modo TRADITIONAL incluye el modo NO_ZERO_IN_DATE. En el modo permisivo por defecto de MySQL, se inserta el siguiente valor:

mysql> SET sql_mode=''; Query OK, 0 rows affected (0.14 sec)

mysql> INSERT INTO datetest VALUES('12:00:00'); Query OK, 1 row affected (0.12 sec)

mysql> SELECT d FROM datetest; +------------+ | d |

+------------+ | 2012-00-00 | +------------+

MySQL interpreta el valor insertado como una fecha de dos dgitos (el ao 12), y lo convierte en una fecha de 4 dgitos (ao 2012). Las otras partes de la columna de tipo DATE (mes y da) se establecen a cero. 5. Explique si las siguientes declaraciones son verdaderas o falsas. El conjunto de caracteres de una columna est determinado por el conjunto de caracteres de su tabla. Lo mismo se aplica para su ordenacin. Las sentencias no son completamente ciertas. S es cierto que el conjunto de caracteres de una columna viene determinado por defecto por el de la tabla si la definicin de la columna no especifica ningn conjunto. Si la definicin de la columna tambin omite la ordenacin, la ordenacin por defecto de la tabla se asignar a la columna.

Apndice B

6. Cada

conjunto

de

caracteres

tiene

exactamente

una

compaginacin

(Verdadero o Falso). Esto no es cierto. Un conjunto de caracteres puede tener ms de una ordenacin, de hecho la mayora lo tiene. Por ejemplo:

mysql> SHOW COLLATION LIKE 'hebrew%'; +-------------------+---------+----+---------+----------+---------+ | Collation | Charset | Id | Default | Compiled | Sortlen |

+-------------------+---------+----+---------+----------+---------+ | hebrew_general_ci | hebrew | hebrew_bin | hebrew | 16 | Yes | 71 | | Yes | Yes | | 1 | 1 |

+-------------------+---------+----+---------+----------+---------+

7. A continuacin, se describe la estructura de la tabla continente que tiene una columna (name, que guarda nombres de continentes). Se supone que el modo SQL no tiene restricciones para la entrada de datos.

mysql> DESCRIBE continent\G *************************** 1. row *************************** Field: name Type: enum('Africa','America','Antarctica','Asia','Australia','Europe') Null: YES Key: Default: NULL Extra:

Qu valor tipo string ser almacenado con la siguiente operacin de INSERT? Qu valor entero ser almacenado internamente?

mysql> INSERT INTO continent VALUES ('Africa');

El valor de tipo cadena: 'Africa'. El valor entero: 1, porque Africa es el primer miembro en la lista ENUM.

Apndice B

8. La siguiente sentencia CREATE TABLE muestra la definicin para la tabla defaults:

mysql> CREATE TABLE defaults ( -> -> -> -> -> -> -> -> -> -> -> -> ); id INT UNSIGNED NOT NULL UNIQUE, col1 INT NULL, col2 INT NOT NULL, col3 INT DEFAULT 42, col4 CHAR(5) NULL, col5 CHAR(5) NOT NULL, col6 CHAR(5) DEFAULT 'yoo', col7 TEXT NULL, col8 TEXT NOT NULL, col9 TIME NOT NULL, col10 DATE NULL,

Cul es el efecto de la siguiente sentencia INSERT sobre las columnas tipo TEXT? Por qu?

mysql> INSERT INTO defaults (id) VALUES (1);

Estos valores se insertarn en las columnas TEXT de la tabla (se muestra slo una parte):

mysql> SELECT * FROM defaults\G *************************** 1. row *************************** id: 1 ... col7: NULL col8: ...

col7: Esta columna puede aceptar valores nulos, el valor insertado es NULL. col8: Esta columna est declarada como NOT NULL. Dado que el INSERT no proporciona explcitamente un valor para esta columna, MySQL asigna el valor implcito para columnas de tipo cadena, en este caso '' (cadena vaca). No se puede declarar un valor por defecto para una columna de tipo TEXT. Nota: Se obtendr un error si el modo SQL est establecido a STRICT.

Apndice B

CAPTULO 7: EXPRESIONES SQL. Prctica adicional. 1. Qu da de la semana ser dentro de 1 ao y 2 meses a partir de la presente fecha?

mysql> SELECT DAYNAME(NOW() + INTERVAL 1 YEAR + INTERVAL 2 MONTH);

2. Cul es la longitud ms grande y ms pequea de los nombres de ciudad contenidos en la tabla City?

mysql> SELECT MAX(CHAR_LENGTH(name)) as longest, -> MIN(CHAR_LENGTH(Name)) AS shortest FROM City; +---------+----------+ | longest | shortest | +---------+----------+ | 33 | 3 |

+---------+----------+ 1 row in set (0.34 sec)

3. Listar las primeras 5 filas resultantes de las poblaciones contenidas en la tabla Country, redondeando a 6 posiciones a la izquierda del punto decimal.

mysql> SELECT ROUND(Population, -6) FROM Country LIMIT 5; +-----------------------+ | ROUND(Population, -6) | +-----------------------+ | | | | | 0 | 23000000 | 13000000 | 0 | 3000000 |

+-----------------------+ 5 rows in set (0.16 sec)

Apndice B

4. Listar todos los nombres de pases cuya esperanza de vida no puede ser calculada.

mysql> SELECT Name FROM Country WHERE ISNULL(LifeExpectancy); +----------------------------------------------+ | Name |

+----------------------------------------------+ | Antarctica | French Southern territories | Bouvet Island | Cocos (Keeling) Islands | Christmas Island | Falkland Islands | Heard Island and McDonald Islands | British Indian Ocean Territory | Norfolk Island | Niue | Pitcairn | | | | | | | | | | |

| South Georgia and the South Sandwich Islands | | Svalbard and Jan Mayen | Tokelau | United States Minor Outlying Islands | Holy See (Vatican City State) | Wallis and Futuna | | | | |

+----------------------------------------------+ 17 rows in set (0.00 sec)

5. Con qu combinacin de dos caracteres comienzan la mayora de los nombres de pases?

mysql> SELECT LEFT(Name,2) AS TwoChars, COUNT(*) AS Countries -> FROM Country GROUP BY TwoChars ORDER BY Countries DESC LIMIT 1; +----------+-----------+ | TwoChars | Countries | +----------+-----------+ | Ma | 13 |

+----------+-----------+ 1 row in set (0.01 sec)

Apndice B

6. Seleccionar la fecha actual y formatear la salida para que quede en el siguiente formato: nombre_mes da, ao (4 dgitos).

mysql> SHOW VARIABLES LIKE '%format'; +---------------------+-------------------+ | Variable_name | Value |

+---------------------+-------------------+ | binlog_format | date_format | datetime_format | STATEMENT | %Y-%m-%d | |

| %Y-%m-%d %H:%i:%s | | |

| default_week_format | 0 | time_format | %H:%i:%s

+---------------------+-------------------+ 5 rows in set (0.05 sec)

7. Listar todos los pases de Asia que aparezcan con su regin contenida entre parntesis, despus del nombre (por ejemplo: Cyprus (Middle East)).

mysql>

SELECT

CONCAT(Name,

'

(',

Region,

')') AS Country FROM Country -> WHERE Continent = 'Asia'; +------------------------------------------+ | Country |

+------------------------------------------+ | Afghanistan (Southern and Central Asia) | United Arab Emirates (Middle East) | Armenia (Middle East) | Azerbaijan (Middle East) : | Uzbekistan (Southern and Central Asia) | Vietnam (Southeast Asia) | Yemen (Middle East) | | | | : | | |

+------------------------------------------+ 51 rows in set (0.04 sec)

Apndice B

8. Listar el nombre de los pases cuyos nombres contienen las letras a, c y s.

mysql> SELECT Name FROM Country -> WHERE Name LIKE '%a%' AND Name LIKE '%c%' -> AND Name LIKE '%s%'; +----------------------------------------------+ | Name |

+----------------------------------------------+ | American Samoa | Cocos (Keeling) Islands | Cook Islands | Costa Rica | Christmas Island | Cayman Islands | Micronesia, Federated States of | Heard Island and McDonald Islands | British Indian Ocean Territory | Saint Lucia | Madagascar | French Polynesia | | | | | | | | | | | |

| South Georgia and the South Sandwich Islands | | Sao Tome and Principe | Turks and Caicos Islands | Holy See (Vatican City State) | Saint Vincent and the Grenadines | South Africa | | | | |

+----------------------------------------------+ 18 rows in set (0.02 sec)

9. Listar la esperanza de vida promedio de cada continente, redondeada al entero ms cercano.

mysql> SELECT Continent, ROUND(AVG(LifeExpectancy)) AS AvgLifeExp -> FROM Country -> GROUP BY Continent; +---------------+------------+ | Continent | AvgLifeExp |

+---------------+------------+ | Asia | Europe | | 67 | 75 | 73 | 53 | 70 | NULL | 71 |

| North America | | Africa | Oceania | Antarctica | | |

| South America |

Apndice B

+---------------+------------+ 7 rows in set (0.00 sec)

10. Crear el siguiente resultado mediante la consulta a la tabla Country:

+------------+-----------+ | WorldPop | EuropePop |

+------------+-----------+ | 6078749450 | 730074600 | +------------+-----------+

mysql> SELECT SUM(Population) AS WorldPop, -> SUM(IF(Continent='Europe',Population,0))AS EuropePop -> FROM Country; +------------+-----------+ | WorldPop | EuropePop |

+------------+-----------+ | 6078749450 | 730074600 | +------------+-----------+ 1 row in set (0.02 sec)

11. En los registros de cada pas, existe un campo que guarda la forma de gobierno vigente en ese pas (GovernmentForm). Usando este campo, encontrar la distribucin de las formas de gobierno para cada continente. A continuacin, se muestra un ejemplo de la salida resultante de las formas de gobierno ms populares por pas y por continente:

+----------------+------+------+------+------+------+------+------+-------+ | GovernmentForm | Eu | Af | Asi | NA | SA | Oc | An | Total |

+----------------+------+------+------+------+------+------+------+-------+ | Republic | 25 | 46 | 26 | 10 | 9 | 6 | 0 | 122 |

+----------------+------+------+------+------+------+------+------+-------+

mysql> SELECT GovernmentForm, COUNT(*) FROM Country -> GROUP BY GovernmentForm ORDER BY COUNT(*) DESC LIMIT 5; +-------------------------------+----------+ | GovernmentForm | COUNT(*) |

+-------------------------------+----------+ | Republic | Constitutional Monarchy | Federal Republic | | | 122 | 29 | 15 | 12 | 5 |

| Dependent Territory of the UK | | Monarchy |

Apndice B

+-------------------------------+----------+ 5 rows in set (0.00 sec)

mysql> SELECT GovernmentForm, -> SUM(IF(Continent='Europe',1,0)) AS Eu, -> SUM(IF(Continent='Africa',1,0)) AS Af, -> SUM(IF(Continent='Asia',1,0)) AS Asi, -> SUM(IF(Continent='North America',1,0)) AS NA, -> SUM(IF(Continent='South America',1,0)) AS SA, -> SUM(IF(Continent='Oceania',1,0)) AS Oc, -> SUM(IF(Continent='Antarctica',1,0)) AS An, -> COUNT(*) as Total FROM Country -> GROUP BY GovernmentForm ORDER BY Total DESC LIMIT 5; +-------------------------------+------+------+------+------+------+------+------+-------+ | GovernmentForm | Eu | Af | Asi | NA | SA | Oc | An | Total |

+-------------------------------+------+------+------+------+------+------+------+-------+ | Republic | Constitutional Monarchy | Federal Republic | | | 25 | 9 | 5 | 1 | 0 | 46 | 2 | 2 | 2 | 1 | 26 | 5 | 2 | 0 | 3 | 10 | 9 | 2 | 6 | 0 | 9 | 0 | 3 | 1 | 0 | 6 | 4 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 122 | 29 | 15 | 12 | 5 |

| Dependent Territory of the UK | | Monarchy |

+-------------------------------+------+------+------+------+------+------+------+-------+ 5 rows in set (0.03 sec)

CAPTULO 9: BASES DE DATOS. Cuestionario. 1. Dar un vistazo a las tablas de la base de datos world usando la sentencia DESCRIBE. Segn el examen realizado sobre las tablas, cul se dira que es el propsito de esta base de datos? Despus de examinar los registros contenidos en la base de datos world, se puede concluir que la base de datos se usa para almacenar informacin sobre cada uno de los pases en el mundo, incluyendo datos de los idiomas y ciudades. El propsito principal es almacenar y devolver esta informacin, as como permitir a los usuarios manipular los datos cuando sea necesario.

Apndice B

2. Explicar las razones para escoger las tablas, entidades e identificadores. Cmo se us la normalizacin? Se eligieron tres tablas como una separacin lgica de datos. Country -> Primary Key (Code), Foreign Key (Capital) Designado con el propsito de hacer cada fila nica. City -> Primary Key (ID), Foreign Key (CountryCode) Clave primaria para unicidad, la clave fornea relaciona las tablas Country y CountryLanguage. CountryLanguage -> Clave compuesta (CountryCode, Language) La razn de esto es que para que las otras columnas estn definidas se necesita un idioma y un pas. La columna CountryCode relaciona las tablas Country y City. 3. Explicar las relaciones entre las entidades dentro de las tablas que tendrn relacin con otras entidades contenidas en otras tablas. CountryLanguage.CountryCode <-> Country.Code City.CountryCode <-> Country.Code Country.Capital <-> City.Id 4. Listar algunos ejemplos dentro de la base de datos world donde no se us normalizacin. Nota que las tablas en la base de datos world no estn en 3FN. En la tabla Country la columna Continent es dependiente de la columna Region.

Apndice B

CAPTULO 10: TABLAS. Prctica adicional. 1. Cambiar la base de datos actual a la base de datos test.

mysql> use test Database changed

2. Crear dos nuevas tablas: a) 'students' con dos columnas: ['id' de tipo SMALLINT UNSIGNED, con los siguientes atributos: AUTO_INCREMENT, PRIMARY KEY] y ['name' con los siguientes atributos: VARCHAR(100)]. b) 'enrollments' con dos columnas: ['studentid' de tipo SMALLINT UNSIGNED] y ['name' con los siguientes atributos: VARCHAR(100) y valor por defecto NULL]. Mostrar la sentencia CREATE TABLE para ambas tablas para confirmar su correcta creacin.

mysql> CREATE TABLE students(id smallint unsigned primary key -> auto_increment, name varchar(100)); Query OK, 0 rows affected (0.13 sec)

mysql> SHOW CREATE TABLE students\G *************************** 1. row *************************** Table: students Create Table: CREATE TABLE `students` ( `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.02 sec)

mysql> CREATE TABLE enrollments (studentid smallint unsigned, -> name varchar(100)); Query OK, 0 rows affected (0.17 sec)

mysql> SHOW CREATE TABLE enrollments\G *************************** 1. row ***************************

Apndice B

Table: enrollments Create Table: CREATE TABLE `enrollments` ( `studentid` smallint(5) unsigned DEFAULT NULL, `name` varchar(100) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.00 sec)

3. Alterar la tabla enrollments para asignarle en forma explcita el motor de almacenamiento InnoDB a fin de soportar claves forneas.

mysql> ALTER TABLE enrollments ENGINE=InnoDB; Query OK, 0 rows affected (0.38 sec) Records: 0 Duplicates: 0 Warnings: 0

4. Definir la columna studentid de la tabla enrollments como clave fornea con una referencia a la columna id de la tabla students. Mostrar la sentencia CREATE TABLE para confirmar que se efectu el cambio.

mysql> ALTER TABLE enrollments ADD FOREIGN KEY (studentid) -> REFERENCES students(id); Query OK, 0 rows affected (0.23 sec) Records: 0 Duplicates: 0 Warnings: 0

mysql> SHOW CREATE TABLE enrollments\G *************************** 1. row *************************** Table: enrollments Create Table: CREATE TABLE `enrollments` ( `studentid` smallint(5) unsigned DEFAULT NULL, `name` varchar(100) DEFAULT NULL, KEY `studentid` (`studentid`), CONSTRAINT `enrollments_ibfk_1` FOREIGN KEY (`studentid`) REFERENCES

`students` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.03 sec)

Apndice B

5. Modificar la tabla enrollments para cambiar la longitud de la secuencia de caracteres de la columna name a 50 y agregar un valor por defecto de 'New Student' y no permitir valores NULL. Confirmar la nueva estructura de la tabla.

mysql> ALTER TABLE enrollments MODIFY name VARCHAR(50) DEFAULT 'New '> Student' NOT NULL; Query OK, 0 rows affected (0.20 sec) Records: 0 Duplicates: 0 Warnings: 0

mysql> SHOW CREATE TABLE enrollments\G *************************** 1. row *************************** Table: enrollments Create Table: CREATE TABLE `enrollments` ( `studentid` smallint(5) unsigned DEFAULT NULL, `name` varchar(50) NOT NULL DEFAULT 'New Student', KEY `studentid` (`studentid`), CONSTRAINT `enrollments_ibfk_1` FOREIGN KEY (`studentid`) REFERENCES `students` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.01 sec)

mysql> DESC enrollments; +-----------+----------------------+------+-----+--------------+-------+ | Field | Type | Null | Key | Default | Extra |

+-----------+----------------------+------+-----+--------------+-------+ | studentid | smallint(5) unsigned | YES | name | varchar(50) | NO | MUL | NULL | | New Student | | | |

+-----------+----------------------+------+-----+--------------+-------+ 2 rows in set (0.07 sec)

6. Renombrar la tabla enrollments a t2.

mysql> ALTER TABLE enrollments RENAME t2; Query OK, 0 rows affected (0.07 sec)

Apndice B

7. Eliminar la tabla enrollments si existe. Verificar mensajes de alerta.

mysql> DROP TABLE IF EXISTS test_table; Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> SHOW WARNINGS; +-------+------+----------------------------+ | Level | Code | Message |

+-------+------+----------------------------+ | Note | 1051 | Unknown table 'test_table' |

+-------+------+----------------------------+ 1 row in set (0.02 sec)

8. Eliminar las tablas t2 y students. Confirmar que ya no existe ninguna de las tablas.

mysql> DROP TABLE IF EXISTS t2; Query OK, 0 rows affected (0.07 sec)

mysql> DROP TABLE IF EXISTS students; Query OK, 0 rows affected (0.03 sec)

mysql> SHOW TABLES;

9. Se requiere crear dos nuevas tablas dentro de la base de datos world a fin de realizar el siguiente ejercicio: Tabla 1:

mysql> CREATE TABLE europe SELECT name, population FROM country -> WHERE continent='europe'; Query OK, 46 rows affected (0.13 sec) Records: 46 Duplicates: 0 Warnings: 0

Tabla 2:

mysql> CREATE TABLE asia SELECT name, population FROM country -> WHERE continent='asia'; Query OK, 51 rows affected (0.10 sec) Records: 51 Duplicates: 0 Warnings: 0

Apndice B

a)

mysql> SELECT * FROM europe -> UNION -> SELECT * FROM asia; +-------------------------------+------------+ | name | population |

+-------------------------------+------------+ | Albania | Andorra | Austria | Belgium | Bulgaria | Bosnia and Herzegovina : | Russian Federation | Svalbard and Jan Mayen | San Marino | Slovakia | Slovenia | Sweden | Ukraine | | | | | | | | | | | | | 3401200 | 78000 | 8091800 | 10239000 | 8190900 | 3972000 | : 146934000 | 3200 | 27000 | 5398700 | 1987800 | 8861400 | 50456000 | 1000 | : | | 79832000 | 18112000 |

| Holy See (Vatican City State) | : | Vietnam | Yemen

+-------------------------------+------------+ 97 rows in set (0.03 sec)

b)

mysql> SELECT name, population FROM europe WHERE population<500000 -> UNION -> SELECT population, name FROM asia WHERE population>10000000; +---------------------------------+-------------+ | name | population |

+---------------------------------+-------------+ | Andorra | Faroe Islands : | San Marino | Holy See (Vatican City State) | 22720000 | 129155000 : | 27000 | 1000 | 78000 | 43000 | | : | |

| Afghanistan | | Bangladesh | :

Apndice B

| 79832000 | 18112000

| Vietnam | Yemen

| |

+---------------------------------+-------------+ 37 rows in set (0.02 sec)

Ayuda: Tratar de usar la clusula UNION con la sentencia SELECT. A continuacin, se ofrece unos ejercicios opcionales de esta Prctica adicional: 10 Y 11. Estos son ejercicios adicionales que pueden variar en funcin del alumno. Consulta con el instructor si tienes cualquier duda. En este sentido, estos ejercicios son una extensin del laboratorio de normalizacin de bases de datos del captulo Bases de Datos.

CAPTULO 11: MANIPULACIN DE DATOS DE LAS TABLAS. Prctica adicional. 1. Crear una base de datos llamada world_copy.

mysql> CREATE DATABASE world_copy; Query OK, 1 row affected (0.14 sec)

2. Crear las mismas tablas en world_copy como si fuera la copia de la base de datos world (misma estructura y contenido).

mysql> USE world_copy; Database changed mysql> CREATE TABLE Country LIKE world.Country; Query OK, 0 rows affected (0.51 sec)

mysql> INSERT INTO Country SELECT * FROM world.Country; Query OK, 239 rows affected (0.25 sec) Records: 239 Duplicates: 0 Warnings: 0

mysql> CREATE TABLE CountryLanguage LIKE world.CountryLanguage; Query OK, 0 rows affected (0.23 sec)

mysql> INSERT INTO CountryLanguage SELECT * FROM world.CountryLanguage; Query OK, 984 rows affected (0.11 sec)

Apndice B

Records: 984

Duplicates: 0

Warnings: 0

mysql> CREATE TABLE City LIKE world.City; Query OK, 0 rows affected (0.22 sec)

mysql> INSERT INTO City SELECT * FROM world.City; Query OK, 4079 rows affected (0.12 sec) Records: 4079 Duplicates: 0 Warnings: 0

3. Insertar una nueva ciudad en la tabla City de la nueva base de datos world_copy 'California'. con los siguientes valores para las columnas Name, CountryCode, Population y District, respectivamente: 'Sarah City', 'USA', 1,

mysql> INSERT INTO City (name, countrycode, population, district) -> VALUES ('Sarah City', 'USA', 1, 'California'); Query OK, 1 row affected (0.01 sec)

4. Obtener el valor generado para la columna ID de la fila recin insertada.

mysql> SELECT last_insert_id(); +------------------+ | last_insert_id() | +------------------+ | 4080 |

+------------------+ 1 row in set (0.03 sec)

5. Usar REPLACE en vez de INSERT para llevar a cabo el mismo cambio que en el paso 3, salvo que ahora se cambiar el nombre de la ciudad a 'Steve City'. Con esto, se elimina la ciudad original 'Sarah City'?

mysql> REPLACE INTO City (name, countrycode, population, district) -> VALUES ('Steve City','USA',1,'California'); Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM City WHERE Name='Sarah City'; +------+------------+-------------+------------+------------+ | ID | Name | CountryCode | District | Population |

+------+------------+-------------+------------+------------+ | 4080 | Sarah City | USA | California | 1 |

+------+------------+-------------+------------+------------+ 1 row in set (0.03 sec)

Apndice B

mysql> SELECT * FROM City WHERE Name='Steve City'; +------+------------+-------------+------------+------------+ | ID | Name | CountryCode | District | Population |

+------+------------+-------------+------------+------------+ | 4081 | Steve City | USA | California | 1 |

+------+------------+-------------+------------+------------+ 1 row in set (0.00 sec)

6. Asegurarse de que el SQL Mode est vaco (' ').

mysql> SET sql_mode='';

7. Crear una tabla con una columna TINYINT.

mysql> CREATE TABLE t (t tinyint);

8. Insertar (con INSERT) los valores 'test' y 500 en la tabla. Verificar los valores.

mysql> INSERT INTO t VALUES ('test'); Query OK, 1 row affected, 1 warning (0.02 sec)

mysql> INSERT INTO t VALUES ('500'); Query OK, 1 row affected, 1 warning (0.04 sec)

mysql> SELECT * FROM t; +------+ | t |

+------+ | | 0 | 127 |

+------+ 2 rows in set (0.00 sec)

9. Cambiar el SQL Mode a 'TRADITIONAL'.

mysql> set sql_mode='TRADITIONAL';

Apndice B

10. Tratar de insertar de nuevo 'test' y 500.

mysql> INSERT INTO t VALUES ('test'); ERROR 1366 (HY000): Incorrect integer value: 'test' for column 't' at row 1

mysql> INSERT INTO t VALUES ('500'); ERROR 1264 (22003): Out of range value for column 't' at row 1

11. Usando la sentencia REPLACE, configurar un pas europeo y agregarlo en la tabla Country de la base de datos world_copy.

mysql> REPLACE INTO Country (Code, Name, Continent, Population) -> VALUES ('OZ', 'Country of Oz', 'Europe', 1000000); Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM Country WHERE Code='OZ'\G *************************** 1. row *************************** Code: OZ Name: Country of Oz Continent: Europe Region: SurfaceArea: 0.00 IndepYear: NULL Population: 1000000 LifeExpectancy: NULL GNP: NULL GNPOld: NULL LocalName: GovernmentForm: HeadOfState: NULL Capital: NULL Code2: 1 row in set (0.02 sec)

12. Cambiar el GNP (Producto Territorial Bruto, por sus siglas en ingls) del pas en cuestin a 123000.

mysql> UPDATE Country SET GNP = 123000 WHERE Code='Oz'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0

Apndice B

13. Incrementar la poblacin (Population) del pas en 10%.

mysql> UPDATE Country SET population = population*1.1 WHERE Code='Oz'; Query OK, 1 row affected (0.04 sec) Rows matched: 1 Changed: 1 Warnings: 0

14. Crear una nueva tabla que contenga todos los pases europeos.

mysql> CREATE TABLE ECity SELECT * FROM Country -> WHERE Continent = 'Europe'; Query OK, 47 rows affected (0.40 sec) Records: 47 Duplicates: 0 Warnings: 0

15. Eliminar el pas que se ingres de la tabla Country.

mysql> DELETE FROM Country WHERE Code='Oz'; Query OK, 1 row affected (0.00 sec)

CAPTULO 12: TRANSACCIONES. Cuestionario. 1. Qu es una transaccin? Una transaccin es una agrupacin lgica de sentencias que son manejadas por el servidor como una unidad. 2. Cules son las implicaciones de no estar en modo autocommit? Al confirmar o revertir una transaccin comenzara una nueva transaccin. De esta forma, se estara obligado a confirmar manualmente las transacciones. 3. Qu significa el trmino ACID? Atmico (Atomic), Consistente (Consistent), Aislado (Isolated) y Duradero (Durable). 4. Nombrar los cuatro niveles de aislamiento de transacciones. READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE.

Apndice B

5. Cules son las tres clases de inconsistencias que pueden ocurrir en el caso de transacciones simultneas que acceden a la misma tabla? Lecturas sucias, lecturas no repetibles y lecturas fantasmas. 6. Un nivel SERIALIZABLE permite lecturas no repetibles. (Verdadero o Falso). Falso. 7. Los dos modificadores de bloqueos que InnoDB soporta son: LOCK IN SHARE MODE y FOR UPDATE. 8. Ambos tipos de bloqueo bloquearn las filas seleccionadas para evitar que ocurran problemas cuando se da un acceso simultneo a los datos de una tabla. Prctica adicional. 1. Asegurarse de que el motor de almacenamiento de la tabla City es InnoDB.

mysql> ALTER TABLE City ENGINE = InnoDB; Query OK, 4079 rows affected (0.40 sec) Records: 4079 Duplicates: 0 Warnings: 0

2. Arrancar una nueva transaccin: Cuntas filas tiene la tabla City? Eliminar todas las filas de esa tabla.

mysql> START TRANSACTION; (o BEGIN;) Query OK, 0 rows affected (0.01 sec)

mysql> SELECT COUNT(*) FROM City; +----------+ | COUNT(*) | +----------+ | 4079 |

+----------+ 1 row in set (0.03 sec)

Apndice B

3. Si la transaccin es anulada (revertida), cuntas filas tendr la tabla? Anular la transaccin y verlo. Si se anula la transaccin, la sentencia DELETE se cancelar y las tablas volvern a tener 4079.

mysql> ROLLBACK; Query OK, 0 rows affected (0.21 sec)

mysql> SELECT COUNT(*) FROM City; +----------+ | COUNT(*) | +----------+ | 4079 |

+----------+ 1 row in set (0.03 sec)

4. Arrancar una nueva transaccin (t1).

mysql> START TRANSACTION; (o BEGIN;) Query OK, 0 rows affected (0.01 sec)

5. En t1, hacer SELECT de todas las filas de la tabla City cuyo id > 4070.

mysql> SELECT * FROM City WHERE Id > 4070; +------+--------------+-------------+------------+------------+ | ID | Name | CountryCode | District | Population |

+------+--------------+-------------+------------+------------+ | 4071 | Mount Darwin | ZWE | 4072 | Mutare | 4073 | Gweru | 4074 | Gaza | 4075 | Khan Yunis | 4076 | Hebron | 4077 | Jabaliya | 4078 | Nablus | 4079 | Rafah | ZWE | ZWE | PSE | PSE | PSE | PSE | PSE | PSE | Harare | 164362 | 131367 | 128037 | 353632 | 123175 | 119401 | 113901 | 100231 | 92020 |

| Manicaland | | Midlands | Gaza | |

| Khan Yunis | | Hebron |

| North Gaza | | Nablus | Rafah | |

+------+--------------+-------------+------------+------------+ 9 rows in set (0.01 sec)

Apndice B

6. Abrir otra conexin de cliente al Servidor MySQL y arrancar otra transaccin (t2).

mysql> START TRANSACTION; (o BEGIN;) Query OK, 0 rows affected (0.01 sec)

7. En t2, hacer SELECT de todas las filas de la tabla City cuyo id > 4070.

mysql> SELECT * FROM City WHERE Id > 4070; +------+--------------+-------------+------------+------------+ | ID | Name | CountryCode | District | Population |

+------+--------------+-------------+------------+------------+ | 4071 | Mount Darwin | ZWE | 4072 | Mutare | 4073 | Gweru | 4074 | Gaza | 4075 | Khan Yunis | 4076 | Hebron | 4077 | Jabaliya | 4078 | Nablus | 4079 | Rafah | ZWE | ZWE | PSE | PSE | PSE | PSE | PSE | PSE | Harare | 164362 | 131367 | 128037 | 353632 | 123175 | 119401 | 113901 | 100231 | 92020 |

| Manicaland | | Midlands | Gaza | |

| Khan Yunis | | Hebron |

| North Gaza | | Nablus | Rafah | |

+------+--------------+-------------+------------+------------+ 9 rows in set (0.01 sec)

8. En t2, efectuar INSERT de una nueva fila en la tabla City.

mysql> INSERT INTO City (Name, Countrycode) VALUES ('New City', 'ATA'); Query OK, 1 row affected (0.00 sec)

9. Regresar a t1 y enviar de nuevo el SELECT.

mysql> SELECT * FROM City WHERE Id > 4070; +------+--------------+-------------+------------+------------+ | ID | Name | CountryCode | District | Population |

+------+--------------+-------------+------------+------------+ | 4071 | Mount Darwin | ZWE | 4072 | Mutare | 4073 | Gweru | 4074 | Gaza | 4075 | Khan Yunis | 4076 | Hebron | 4077 | Jabaliya | 4078 | Nablus | ZWE | ZWE | PSE | PSE | PSE | PSE | PSE | Harare | 164362 | 131367 | 128037 | 353632 | 123175 | 119401 | 113901 | 100231 |

| Manicaland | | Midlands | Gaza | |

| Khan Yunis | | Hebron |

| North Gaza | | Nablus |

Apndice B

| 4079 | Rafah

| PSE

| Rafah

92020 |

+------+--------------+-------------+------------+------------+ 9 rows in set (0.00 sec)

10. Qu se ve? Qu niveles de aislamiento no pueden estar siendo usados? El mismo resultado. No puede ser READ UNCOMMITTED ni SERIALIZABLE; el primero porque mostrara la fila, y el segundo porque esperara a que el segundo cliente liberara el bloqueo sobre la fila. 11. Ir a t2 y hacer COMMIT de la transaccin.

mysql> COMMIT; Query OK, 0 rows affected (0.01 sec)

12. Regresar a t1 y enviar de nuevo el SELECT.

mysql> SELECT * FROM City WHERE Id > 4070; +------+--------------+-------------+------------+------------+ | ID | Name | CountryCode | District | Population |

+------+--------------+-------------+------------+------------+ | 4071 | Mount Darwin | ZWE | 4072 | Mutare | 4073 | Gweru | 4074 | Gaza | 4075 | Khan Yunis | 4076 | Hebron | 4077 | Jabaliya | 4078 | Nablus | 4079 | Rafah | ZWE | ZWE | PSE | PSE | PSE | PSE | PSE | PSE | Harare | 164362 | 131367 | 128037 | 353632 | 123175 | 119401 | 113901 | 100231 | 92020 |

| Manicaland | | Midlands | Gaza | |

| Khan Yunis | | Hebron |

| North Gaza | | Nablus | Rafah | |

+------+--------------+-------------+------------+------------+ 9 rows in set (0.00 sec)

13. Se ve la fila? Qu nivel de aislamiento se est usando? La fila todava no aparece. No puede ser READ COMMITTED. El nivel de aislamiento que debe estar ejecutndose es REPEATABLE READ.

Apndice B

14. Anular t1 con ROLLBACK y enviar de nuevo el SELECT. Es ahora visible la fila?

mysql> ROLLBACK; Query OK, 0 rows affected (0.01 sec)

mysql> SELECT * FROM City WHERE Id > 4070; +------+--------------+-------------+------------+------------+ | ID | Name | CountryCode | District | Population |

+------+--------------+-------------+------------+------------+ | 4071 | Mount Darwin | ZWE | 4072 | Mutare | 4073 | Gweru | 4074 | Gaza | 4075 | Khan Yunis | 4076 | Hebron | 4077 | Jabaliya | 4078 | Nablus | 4079 | Rafah | 4081 | New City | ZWE | ZWE | PSE | PSE | PSE | PSE | PSE | PSE | ATA | Harare | 164362 | 131367 | 128037 | 353632 | 123175 | 119401 | 113901 | 100231 | 92020 | 0 |

| Manicaland | | Midlands | Gaza | |

| Khan Yunis | | Hebron |

| North Gaza | | Nablus | Rafah | | | |

+------+--------------+-------------+------------+------------+ 10 rows in set (0.00 sec)

15. Repetir los pasos 4 al 14, pero cambiando el nivel de aislamiento de t1 a READ COMMITTED antes de arrancar la transaccin. Cundo se puede ver la fila ahora? Con el nivel de aislamiento cambiado a READ COMMITTED, la fila aparecer en el paso 12. 16. Repetir los pasos 4 al 14, pero cambiando el nivel de aislamiento de t1 a READ UNCOMMITTED antes de arrancar la transaccin. Cundo es visible la fila ahora? Con el nivel de aislamiento cambiado a READ UNCOMMITTED, la fila aparecer en el paso 9.

Apndice B

CAPTULO 13: JOINS. Prctica adicional. 1. Qu idiomas son hablados en Suecia?

mysql> SELECT Language FROM CountryLanguage, Country -> WHERE CountryCode = Code AND Name = 'Sweden'; +---------------------------+ | Language |

+---------------------------+ | Arabic | Finnish | Norwegian | | |

| Southern Slavic Languages | | Spanish | Swedish | |

+---------------------------+ 6 rows in set (0.00 sec)

2. Listar el nombre del pas con el mayor nmero de ciudades.

mysql> SELECT Country.Name, COUNT(City.Name) AS Cities -> FROM Country -> INNER JOIN City ON City.CountryCOde = Country.Code -> GROUP BY Country.Name ORDER BY Cities DESC LIMIT 1; +-------+--------+ | Name | Cities |

+-------+--------+ | China | 363 |

+-------+--------+ 1 row in set (0.08 sec)

3. Listar el nombre de los pases que tienen una o ms ciudades con una poblacin superior a 7000000 de habitantes.

mysql> SELECT DISTINCT Country.Name FROM Country -> INNER JOIN City ON Code = CountryCode -> WHERE City.Population > 7000000; +--------------------+ | Name |

+--------------------+ | Brazil |

Apndice B

| United Kingdom | Indonesia | India | Japan | China | South Korea | Mexico | Pakistan | Turkey

| | | | | | | | |

| Russian Federation | | United States |

+--------------------+ 12 rows in set (0.01 sec)

4. En qu pases no se habla idioma alguno?

mysql> SELECT Country.Name FROM Country LEFT JOIN CountryLanguage -> ON Code=CountryCode WHERE CountryLanguage.CountryCode IS NULL; +----------------------------------------------+ | Name |

+----------------------------------------------+ | Antarctica | French Southern territories | Bouvet Island | Heard Island and McDonald Islands | British Indian Ocean Territory | | | | |

| South Georgia and the South Sandwich Islands | +----------------------------------------------+ 6 rows in set (0.03 sec)

5.

Mostrar una lista de los pases que no tengan su correspondiente capital en la tabla City.

mysql> SELECT Country.Name FROM Country LEFT OUTER JOIN City -> ON Country.Capital = City.Id WHERE ID IS NULL; +----------------------------------------------+ | Name |

+----------------------------------------------+ | Antarctica | French Southern territories | Bouvet Island | Heard Island and McDonald Islands | British Indian Ocean Territory | | | | |

| South Georgia and the South Sandwich Islands | | United States Minor Outlying Islands |

Apndice B

| Country of Oz

+----------------------------------------------+ 8 rows in set (0.01 sec)

6. Listar los pases donde ms de 80% de la poblacin vive en las ciudades de la tabla City.

mysql> SELECT Country.Name FROM Country INNER JOIN City ON -> CountryCode=Code -> GROUP BY Country.Name HAVING SUM(City.Population) / -> MAX(Country.Population) > 0.8; +---------------------------+ | Name |

+---------------------------+ | Cocos (Keeling) Islands | Falkland Islands | Gibraltar | Macao | Pitcairn | | | | |

| Saint Pierre and Miquelon | | Singapore | South Korea | |

+---------------------------+ 8 rows in set (0.05 sec)

7. Usando una sentencia, eliminar el pas 'Zambia', incluyendo todas sus ciudades y los idiomas que se hablan en dicho pas.

mysql> DELETE Country, CountryLanguage, City FROM Country -> JOIN CountryLanguage ON Code = CountryLanguage.CountryCode -> JOIN City ON Code = City.CountryCode -> WHERE Country.Name='Zambia'; Query OK, 14 rows affected (0.59 sec)

Apndice B

CAPTULO 14: SUBCONSULTAS. Cuestionario. 1. En qu lugar dentro de una sentencia SQL puede ser colocada una subconsulta escalar? Una subconsulta escalar se puede colocar en casi cualquier lugar de una sentencia SQL en la que se esperara un valor escalar, as como un escalar real, un argumento de una funcin, un trmino de una expresin matemtica, etc. Algunas excepciones son aquellas en las que se requiere un literal, como los argumentos en las clusulas LIMIT. 2. La siguiente consulta selecciona aquellos continentes con pases donde ms del 50% de la poblacin habla ingls. Es ste un ejemplo del uso de una subconsulta correlacionada? Por qu?

mysql> SELECT DISTINCT Continent -> FROM Country -> WHERE Code IN (SELECT CountryCode -> -> -> FROM CountryLanguage WHERE Language='English' AND Percentage>50);

El ejemplo mostrado no es un ejemplo de subconsulta correlacionada porque la subconsulta puede ejecutarse completamente sin necesidad de escribir la consulta exterior. En una subconsulta correlacionada, el SELECT interior depende de la consulta exterior. 3. La siguiente sentencia usa una subconsulta correlacionada para buscar el pas de Surmerica con la poblacin ms pequea:

mysql> SELECT * FROM Country c1 -> WHERE Continent = 'South America' -> AND Population = (SELECT MIN(Population) FROM Country c2 -> WHERE c2.Continent = c1.Continent);

Apndice B

En la subconsulta anterior, c1 depende de la consulta externa porque el alias de tabla c1 est definido en dicha consulta. Reescribir la sentencia para que utilice una subconsulta no correlacionada. En la subconsulta, c1 depende de la consulta exterior, porque el alias de tabla c1 est definido en esta.

mysql> SELECT * FROM Country -> WHERE Continent = 'South America' -> AND Population = (SELECT MIN(Population) FROM Country -> WHERE Continent = 'South America');

4. El operador de igualdad (=) puede usarse como un constructor de subconsultas WHERE para todos los tipos de resultados de subconsultas. (Verdadero o Falso). Falso. El smbolo de igualdad (=) slo se puede usar para resultados de tipo escalar y de fila. Prctica adicional. 1. Qu pas tiene la ciudad ms poblada del mundo? (Usar una subconsulta que determine la ciudad con la poblacin mxima y luego obtener el nombre del pas asociado).

mysql> SELECT Country.Name -> FROM Country, City -> WHERE Country.Code = City.CountryCode -> AND City.Population = (SELECT MAX(Population) -> +-------+ | Name | FROM City);

+-------+ | India | +-------+ 1 row in set (0.38 sec)

Apndice B

2. Nombrar los pases del continente europeo donde se habla espaol. (Usar una subconsulta que determine los pases [por su cdigo] en el mundo que hablan espaol y luego comparar los cdigos a los correspondientes del continente europeo para filtrar los otros continentes).

mysql> SELECT Name FROM Country WHERE Continent = 'Europe' -> AND Code IN (SELECT CountryCode FROM CountryLanguage -> -> ORDER BY Name; +---------+ | Name | WHERE Language = 'Spanish')

+---------+ | Andorra | | France | Spain | Sweden | | |

+---------+ 4 rows in set (0.03 sec)

3. Buscar todos los pases donde se habla francs pero no ingls.

mysql> SELECT Country.Name FROM Country JOIN CountryLanguage -> ON Code=CountryCode WHERE Code NOT IN -> (SELECT CountryCode FROM CountryLanguage WHERE Language = -> 'English') -> AND CountryLanguage.Language = 'French'; +---------------------------+ | Name |

+---------------------------+ | Andorra | Burundi | Belgium | Switzerland | France | Guadeloupe | Haiti | Italy | Lebanon | Luxembourg | Madagascar | Martinique | Mauritius | Mayotte | New Caledonia | French Polynesia | | | | | | | | | | | | | | | |

Apndice B

| Rwanda

| Saint Pierre and Miquelon | | Sao Tome and Principe |

+---------------------------+ 19 rows in set (0.02 sec)

4. Listar cada pas y la poblacin de su ciudad ms grande.

mysql> SELECT Name, (SELECT MAX(Population) FROM City -> WHERE CountryCode=Code) as LargestCity FROM Country; +----------------------------------------------+-------------+ | Name | LargestCity |

+----------------------------------------------+-------------+ | Afghanistan | Netherlands : | French Southern territories | United States Minor Outlying Islands | | : | | 1780000 | 731200 | : NULL | NULL |

+----------------------------------------------+-------------+ 239 rows in set (#.## sec)

5. Listar cada pas y el nombre de su mayor ciudad.

mysql> SELECT Country.Name AS Country,City.Name AS LargestCity -> FROM Country JOIN (SELECT CountryCode, MAX(Population) AS MaxPop -> FROM City GROUP BY CountryCode) AS tbl -> ON tbl.CountryCode = Country.Code JOIN City -> ON Country.Code = City.CountryCode AND -> City.Population = tbl.MaxPop; +---------------------------------------+-----------------------------------+ | Country | LargestCity |

+---------------------------------------+-----------------------------------+ | Afghanistan | Netherlands : | United States | Virgin Islands, U.S. | Zimbabwe | Palestine | Kabul | Amsterdam : | New York | Charlotte Amalie | Harare | Gaza | | : | | | |

+---------------------------------------+-----------------------------------+ 232 rows in set (0.26 sec)

Apndice B

6. Buscar todas las ciudades que son ms grandes que todas las ciudades de China.

mysql> SELECT Name FROM City WHERE Population > ALL -> (SELECT City.Population FROM City JOIN Country -> ON Code=CountryCode -> WHERE Country.Name = 'China'); +-----------------+ | Name |

+-----------------+ | So Paulo |

| Mumbai (Bombay) | | Seoul |

+-----------------+ 3 rows in set (0.01 sec)

7. Buscar la mayor ciudad de cada continente.

mysql> SELECT c.Continent, city.Name -> FROM Country AS c JOIN city ON Code = CountryCode, -> (SELECT Continent, MAX(City.Population) -> AS Population FROM Country JOIN City ON Code = CountryCode -> GROUP BY Continent) AS tbl -> WHERE c.Continent = tbl.Continent AND -> City.Population = tbl.Population; +---------------+------------------+ | Continent | Name |

+---------------+------------------+ | Oceania | Sydney | | | |

| South America | So Paulo | Africa | Asia | Cairo | Mumbai (Bombay)

| North America | Ciudad de Mxico | | Europe | Moscow |

+---------------+------------------+ 6 rows in set (0.03 sec)

Apndice B

8. Buscar el nombre de todas las ciudades que estn presentes en ms de 2 continentes.

mysql> SELECT tbl1.Name FROM (SELECT DISTINCT City.Name, Continent -> FROM City JOIN Country ON Code = CountryCode) AS tbl1 -> JOIN (SELECT DISTINCT City.Name, Continent FROM City JOIN Country -> ON Code = CountryCode) AS tbl2 -> ON tbl1.Name = tbl2.Name AND tbl1.Continent <> tbl2.Continent -> GROUP BY tbl1.Name HAVING COUNT(*) > 2; +------------+ | Name |

+------------+ | Crdoba |

| San Miguel | | Toledo | Valencia | Victoria | | |

+------------+ 5 rows in set (#.## sec)

Una sentencia simple (sin usar subconsultas) que obtiene el mismo resultado puede ser:

mysql> SELECT City.Name FROM City JOIN Country -> ON City.CountryCode = Country.Code -> GROUP BY City.Name -> HAVING COUNT(DISTINCT Continent) > 2; +------------+ | Name |

+------------+ | Crdoba |

| San Miguel | | Toledo | Valencia | Victoria | | |

+------------+ 5 rows in set (0.14 sec)

Apndice B

9. Listar el nombre de todos los pases que tienen nombres de ciudad duplicados.

mysql> SELECT Name FROM Country WHERE EXISTS -> (SELECT Name FROM City WHERE CountryCode=Country.Code -> GROUP BY Name HAVING COUNT(Name)>1); +--------------------+ | Name |

+--------------------+ | Philippines | Indonesia | China | Mexico | | | |

| Russian Federation | | United States |

+--------------------+ 6 rows in set (#.## sec)

CAPTULO 15: VISTAS. Prctica adicional. 1. Crear una vista 'CapitalesPaises' que consiste en un join de las tablas Country y City y contiene las columnas Code, Country.Name, Continent, City.Name y City.Id. Esta vista es actualizable? Es insertable?

mysql> CREATE VIEW CountryCapitals AS -> SELECT CountryCode, Country.Name AS Country, City.Name AS Capital, -> City.Id AS CapitalID FROM Country JOIN City ON Capital = ID; Query OK, 0 rows affected (0.11 sec)

Es actualizable. Es insertable, siempre y cuando se usen slo columnas de una de las tablas.

Apndice B

2. Crear una vista 'Idiomas' que contiene una fila por cada idioma (Language), el nmero de personas que lo habla y una lista de los pases donde se habla el idioma.

mysql> CREATE VIEW Language AS SELECT Language, -> ROUND(SUM(Population*Percentage/100),0) AS Speakers, -> GROUP_CONCAT(Name) AS Countries FROM Country JOIN CountryLanguage -> ON Code = CountryCode GROUP BY Language; Query OK, 0 rows affected (0.10 sec)

3. Reemplazar

la

vista

existente

llamada

'vista_europa'

(creada

en

el

laboratorio anterior) y llenar con datos de la base de datos Country las columnas Code, Name y Continent donde el continente sea 'Europe', asegurndose de que todas las actualizaciones sean verificadas antes de ser efectuadas.

mysql> CREATE OR REPLACE VIEW europe_view AS SELECT code, name, continent -> FROM Country WHERE Continent='europe' WITH CHECK OPTION; Query OK, 0 rows affected (0.04 sec)

4. Cambiar el nombre (name) del continente cuyo cdigo (code) es 'DEU' a 'Asia' en la nueva vista 'vista_europa'. Explicar el resultado.

mysql> UPDATE europe_view SET Continent='Asia' WHERE Code='DEU'; ERROR 1369 (HY000): CHECK OPTION failed 'world.europe_view'

La clusula WITH CHECK OPTION de la sentencia CREATE previene que actualizacin del pas se lleve a cabo si no pasa la opcin de comprobacin. 5. Se desea garantizar que despus de una insercin (INSERT) y/o

actualizacin (UPDATE), cada ciudad (City) corresponda al pas correcto en la tabla Country. Cmo se puede lograr eso? Ayuda: La vista requerir una subconsulta para ser creada de forma precisa. Esto podra realizarse con un disparador, pero no de forma limpia. No hay forma de elevar una excepcin (o algo similar), as que se debera ejecutar una consulta que cause un error (como usar una tabla que no exista o insertar una fila con un valor de PK que ya exista).

Apndice B

Una solucin ms limpia sera crear una vista que fuera una interfaz a los datos. La vista se crear con el nico propsito de insertar o modificar filas:

mysql> CREATE VIEW City_v AS -> SELECT * FROM City WHERE CountryCode IN -> (SELECT Code FROM Country) -> WITH CASCADED CHECK OPTION; Query OK, 0 rows affected (0.06 sec)

Como la vista se ha creado con la opcin de comprobacin, todas las filas insertadas a travs de la vista deben pasar la comprobacin. En este caso, la comprobacin exige que el CountryCode de una ciudad exista en la tabla Country. 6. Crear una vista 'ContFrances' que contenga los continentes con pases donde ms de 20% de su poblacin hable francs. Confirmar que existe la nueva vista y listar todo su contenido.

mysql> CREATE VIEW FrenchCont AS -> SELECT DISTINCT Continent -> FROM Country -> WHERE Code IN (SELECT CountryCode -> FROM CountryLanguage -> WHERE Language='French' -> AND Percentage>20); Query OK, 0 rows affected (0.05 sec)

mysql> SHOW FULL TABLES; +-----------------+------------+ | Tables_in_world | Table_type | +-----------------+------------+ | city | city_v | country | BASE TABLE | | VIEW |

| BASE TABLE | |

| countrycapitals | VIEW

| countrylanguage | BASE TABLE | | europe_view | frenchcont | language | VIEW | VIEW | VIEW | | |

+-----------------+------------+ 8 rows in set (0.08 sec)

mysql> SELECT * FROM FrenchCont LIMIT 10; +---------------+ | Continent |

Apndice B

+---------------+ | Europe |

| North America | | Africa | Oceania | |

+---------------+ 4 rows in set (0.01 sec)

CAPTULO 16: SENTENCIAS PREPARADAS. Prctica adicional. 1. Crear una sentencia preparada llamada 'misentencia' que incluya una consulta del nombre en la tabla City, donde id tendr el valor igual a una variable.

mysql> PREPARE misentencia FROM 'SELECT name FROM City WHERE id=?'; Query OK, 0 rows affected (0.02 sec) Statement prepared

2. Asignar a la variable el valor 3567.

mysql> SET @cityid:=3567; Query OK, 0 rows affected (0.00 sec)

3. Ejecutar la sentencia preparada con la variable asignada.

mysql> EXECUTE misentencia USING @cityid; +----------+ | name |

+----------+ | Carpano | +----------+ 1 row in set (0.00 sec)

4. Asignarle a la variable el valor 3568.

mysql> SET @cityid:=3568; Query OK, 0 rows affected (0.00 sec)

Apndice B

5. Volver a ejecutar la sentencia preparada con el nuevo valor de la variable.

mysql> EXECUTE misentencia USING @cityid; +--------------+ | name |

+--------------+ | Catia La Mar | +--------------+ 1 row in set (0.00 sec)

6. Eliminar explcitamente la sentencia preparada recin creada.

mysql> DEALLOCATE PREPARE misentencia; Query OK, 0 rows affected (0.01 sec)

CAPTULO 17: EXPORTACIN E IMPORTACIN DE DATOS. Prctica adicional. 1. Desde el shell del sistema, efectuar un respaldo de la base de datos world haciendo uso de mysqldump. Ver el archivo respaldado.

C:\mysql\bin> mysqldump -u root -p world > C:\worldbackup.sql Enter password: <contrasea>

2. Crear otro archivo con la opcin --skip-opt y comparar los dos archivos. En qu se diferencian uno del otro?

C:\mysql\bin> mysqldump -u root -p --skip-opt world > C:\worldbackup2.sql Enter password: <contrasea>

3. Ingresar en el cliente mysql y crear una nueva base de datos llamada world_old.

mysql> CREATE DATABASE world_old; Query OK, 1 row affected (0.01 sec)

Apndice B

4. Copiar el contenido de world a world_old con el archivo mysqldump (anterior).

C:\mysql\bin> mysql -u root -p world_old < C:\worldbackup.sql Enter password: <contrasea>

5. Usar mysqldump con la opcin --tab=/path para crear un respaldo de la tabla City.

C:\mysql\bin> mysqldump -u root -p --tab=C:\backup world City Enter password: <contrasea>

El directorio C:\backup debe existir, mysqldump no crea directorios. 6. Copiar el contenido de la tabla City en un archivo (City.txt) usando SELECT INTO OUTFILE.

mysql> SELECT * INTO OUTFILE 'C:/City.txt' FROM City; Query OK, 4079 rows affected (0.02 sec)

7. Comparar los archivos creados en los pasos 5 y 6. 8. Crear una tabla City_short llamada con las siguientes columnas: Name CHAR(35), Country CHAR(52), kPopulation INT.

mysql> CREATE TABLE City_short( -> Name char(35) NOT NULL DEFAULT '', -> Country char(52) NOT NULL DEFAULT '', -> kPopulation INT NOT NULL); Query OK, 0 rows affected (0.19 sec)

Apndice B

9. Importar los datos desde el archivo 'City.txt' en la tabla City_short recin creada, usando la sentencia LOAD DATA INFILE de modo que la columna Name tome el nombre de la ciudad, la columna Country es el nombre (name) del pas y la columna kPopulation es la poblacin de la ciudad en miles de habitantes (por ejemplo, si la poblacin es de 2000000, se almacena 2000 en la columna). Verificar que la operacin se realiza exitosamente.

mysql> LOAD DATA INFILE 'C:/City.txt' INTO TABLE City_short -> (@Id,Name,@CountryCode,@District,@Population) -> SET Country = -> (SELECT Name FROM Country WHERE Code = @CountryCode), -> kPopulation = @Population/1000; Query OK, 4079 rows affected (12.62 sec) Records: 4079 Deleted: 0 Skipped: 0 Warnings: 0

mysql> SELECT * FROM City_short LIMIT 20; +------------------+-------------+-------------+ | Name | Country | kPopulation |

+------------------+-------------+-------------+ | Kabul | Qandahar | Herat | Mazar-e-Sharif | Amsterdam | Rotterdam | Haag | Utrecht | Eindhoven | Tilburg | Groningen | Breda | Apeldoorn | Nijmegen | Enschede | Haarlem | Almere | Arnhem | Zaanstad | Afghanistan | | Afghanistan | | Afghanistan | | Afghanistan | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | | Netherlands | 1780 | 238 | 187 | 128 | 731 | 593 | 441 | 234 | 202 | 193 | 173 | 160 | 153 | 152 | 150 | 149 | 142 | 138 | 136 | 129 |

| s-Hertogenbosch | Netherlands |

+------------------+-------------+-------------+ 20 rows in set (0.00 sec)

Apndice B

CAPTULO 18: RUTINAS ALMACENADAS. Prctica adicional. 1. En la base de datos world, crear una funcin c_longitud que devuelva el valor del lado ms largo (hipotenusa) de un tringulo rectngulo basado en la entrada (por parte del usuario final) de los otros dos lados. Probar la funcin con los valores 3 y 4.

mysql> CREATE FUNCTION c_longitud(a INT,B INT) RETURNS DOUBLE RETURN (SQRT(a*a + b*b));

mysql> select c_longitud(3,4); +------------------+ | c_longitud2(3,4) | +------------------+ | 5 |

+------------------+ 1 row in set (0.00 sec)

2. Revisar los detalles del procedimiento c_longitud usando la base de datos INFORMATION_SCHEMA.

mysql> SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME='c_longitud';

3. Crear una funcin llamada factorial que calcular el nmero factorial (n!) de un valor dado. Probar la funcin con los valores 3 y 10.

mysql> DELIMITER // mysql> CREATE FUNCTION factorial(n INT) RETURNS DECIMAL(64,0) -> BEGIN -> DECLARE cnt INT DEFAULT 1; -> DECLARE resultado DECIMAL(64,0) DEFAULT 1; -> /* 49! es el lmite para DECIMAL(64,0) antes de que haya desbordamiento */ -> IF n > 49 THEN -> RETURN(NULL); -> END IF; -> WHILE cnt <= n -> DO -> SET resultado = resultado * cnt; -> SET cnt = cnt + 1; -> END WHILE; -> RETURN(resultado);

Apndice B

-> END // Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;

mysql> SELECT factorial(3); +--------------+ | factorial(3) | +--------------+ | 6 |

+--------------+ 1 row in set (0.02 sec)

mysql> SELECT factorial(10); +---------------+ | factorial(10) | +---------------+ | 3628800 |

+---------------+ 1 row in set (0.00 sec)

4. Crear una funcin llamada nombre_pais que toma el cdigo de pas (country code) de tres caracteres del pas que se tiene como entrada. El resultado sern el nombre del pas basado en su cdigo. Probar el procedimiento con los valores 'RUS' y 'USA'.

mysql> CREATE FUNCTION nombre_pais (country_code CHAR(3)) RETURNS CHAR(52) -> RETURN (SELECT Name FROM country WHERE Code = country_code); Query OK, 0 rows affected (0.00 sec)

mysql> SELECT nombre_pais('RUS'); +--------------------+ | nombre_pais('RUS') | +--------------------+ | Russian Federation | +--------------------+ 1 row in set (0.03 sec)

mysql> SELECT nombre_pais('USA'); +--------------------+ | nombre_pais('USA') | +--------------------+ | United States |

+--------------------+ 1 row in set (0.00 sec)

Apndice B

5. Usar SHOW CREATE para ver la sintaxis usada para crear el procedimiento nombre_pais.

mysql> SHOW CREATE FUNCTION nombre_pais\G *************************** 1. row *************************** Function: nombre_pais sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `nombre_pais`(country_code CHAR(3)) RETURNS char(52) CHARSET latin1 RETURN (SELECT Name FROM country WHERE Code = country_code) character_set_client: latin1 collation_connection: latin1_swedish_ci Database Collation: latin1_swedish_ci 1 row in set (0.00 sec)

6. Crear una funcin capital_pais que devuelve el nombre de la capital de ese pas, tomando el nombre del pas como entrada. Probar la funcin con 'Finland' y 'MySQL'.

mysql> CREATE FUNCTION capital_pais(c_name CHAR(52)) RETURNS CHAR(35) -> RETURN (SELECT City.Name FROM City JOIN Country ON Capital = Id -> WHERE Country.Name = c_name); Query OK, 0 rows affected (0.00 sec)

mysql> SELECT capital_pais('Finland'); +-------------------------+ | capital_pais('Finland') | +-------------------------+ | Helsinki [Helsingfors] |

+-------------------------+ 1 row in set (0.01 sec)

mysql> SELECT capital_pais('MySQL'); +-----------------------+ | capital_pais('MySQL') | +-----------------------+ | NULL |

+-----------------------+ 1 row in set (0.00 sec)

Apndice B

7. Crear un procedimiento que elimine toda la informacin de un pas de la base de datos world (de las tres tablas), en base al nombre del pas. El procedimiento debera informar cuntas filas fueron eliminadas de cada tabla. Probar con 'Germany'.

mysql> DELIMITER // mysql> CREATE PROCEDURE borra_todo_pais(IN c_nombre CHAR(52)) -> inicio: BEGIN -> DECLARE c_code CHAR(3) DEFAULT NULL; -> DECLARE d_paises, d_idiomas, d_ciudades INT DEFAULT 0; -> SELECT Code INTO c_code FROM Country WHERE Name = c_nombre; -> IF ISNULL(c_code) THEN -> SELECT CONCAT('No se ha encontrado Ningn pas con el nombre ',c_nombre) -> AS resultado; -> LEAVE inicio; -> END IF; -> DELETE FROM Country WHERE Code = c_code; -> SELECT ROW_COUNT() INTO d_paises; -> DELETE FROM CountryLanguage WHERE CountryCode = c_code; -> SELECT ROW_COUNT() INTO d_idiomas; -> DELETE FROM City WHERE CountryCode = c_code; -> SELECT ROW_COUNT() INTO d_ciudades; -> SELECT CONCAT('El procedimiento borr ',d_paises,' pais, ',d_ciudades, -> ' ciudades y ',d_idiomas, ' idiomas') AS resultado; -> END // Query OK, 0 rows affected (0.04 sec)

mysql> DELIMITER ; mysql> CALL borra_todo_pais('Germany'); +--------------------------------------------------------+ | resultado |

+--------------------------------------------------------+ | El procedimiento borr 1 pas, 93 ciudades y 6 idiomas | +--------------------------------------------------------+ 1 row in set (0.03 sec)

Query OK, 0 rows affected (0.05 sec)

Apndice B

8. Crear un procedimiento que inserte un nuevo pas en la tabla de pases (country). Los valores a ser suministrados son cdigo (Code), nombre (Name), continente (Continent) y poblacin (Population). Si el cdigo ya existe (error de clave duplicada) debera ser tratado con un manejador. Probar con un pas inventado y con 'SWE', 'MySQL', 'Europe' y 400.

mysql> DELIMITER // mysql> CREATE PROCEDURE inserta_pais(IN c_code CHAR(3), IN c_nombre CHAR(52), -> IN c_cont CHAR(13),IN c_pob INT) -> BEGIN -> DECLARE EXIT HANDLER FOR SQLSTATE '23000' -> SELECT CONCAT('Ya existe un pais con el codigo ',c_code) as error; -> INSERT INTO Country(Code,Name,Continent,Population) -> VALUES(c_code,c_nombre,c_cont,c_pob); -> END // Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ; mysql> CALL inserta_pais('SQL','MySQL','Europe',400); Query OK, 1 row affected (0.00 sec)

mysql> CALL inserta_pais('SWE','MySQL','Europe',400); +-------------------------------------+ | error |

+-------------------------------------+ | Ya existe un pais con el codigo SWE | +-------------------------------------+ 1 row in set (0.01 sec)

Query OK, 0 rows affected (0.03 sec)

9. Crear una funcin que calcule el nmero de la serie Fibonacci de un valor dado (los nmeros de Fibonacci pueden ser descritos con la siguiente frmula recursiva: F(n)=F(n-1)-F(n-2), F(0)=1, F(1)=1). Probar la funcin con 10 y 90.

mysql> DELIMITER // mysql> CREATE FUNCTION fibonacci(n INT) RETURNS DOUBLE -> BEGIN -> DECLARE f1, resultado DOUBLE DEFAULT 0.0; -> DECLARE f2 DOUBLE DEFAULT 1.0; -> DECLARE cnt INT DEFAULT 1; -> WHILE cnt <= n DO -> SET resultado = f1+f2;

Apndice B

-> SET f1 = f2; -> SET f2 = resultado; -> SET cnt = cnt + 1; -> END WHILE; -> RETURN(resultado); -> END // Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ; mysql> SELECT fibonacci(10); +---------------+ | fibonacci(10) | +---------------+ | 89 |

+---------------+ 1 row in set (#.## sec)

mysql> SELECT fibonacci(90); +-----------------------+ | fibonacci(90) |

+-----------------------+ | 4.66004661037553e+018 | +-----------------------+ 1 row in set (#.## sec)

Un estudiante de matemticas podr resolver la ecuacin recursiva (o encontrar la solucin de algn otro lado). La secuencia de Fibonacci tiene una solucin exacta (sin necesidad de bucles) y es de la siguiente forma:

mysql> CREATE FUNCTION fibonacci_rapido(n INT) RETURNS double -> RETURN (SQRT(5)+5)/10*pow(((1+SQRT(5))/2),n) + -> (5-SQRT(5))/10*pow(((1-SQRT(5))/2),n); Query OK, 0 rows affected (0.01 sec)

mysql> SELECT fibonacci_rapido(90); +-----------------------+ | fibonacci_rapido(90) |

+-----------------------+ | 4.66004661037554e+018 | +-----------------------+ 1 row in set (#.## sec)

Apndice B

CAPTULO 19: DISPARADORES. Prctica adicional. 1. Usando la sentencia SHOW, mostrar todas las tablas de la base de datos world.

mysql> SHOW TABLES;

La razn de que usemos el comando SHOW aqu es que veamos las tablas disponibles en la base de datos world. Si se usa SHOW FULL TABLES, se podr ver cules son tablas reales y cules vistas o tablas temporales. Esto puede ayudar a determinar qu tablas pueden tener disparadores y cules no (las vistas y tablas temporales no pueden tener disparadores aplicados). Esto, adems, brinda la oportunidad de asegurarse de que se est dentro de la base de datos world. 2. Crear un disparador sobre la tabla Country para que con cada DELETE de un pas, las tablas City y CountryLanguage cambien apropiadamente.

mysql> DELIMITER // mysql> CREATE TRIGGER ins_pais AFTER DELETE ON Country -> FOR EACH ROW -> BEGIN -> DELETE FROM City WHERE CountryCode = OLD.Code; -> DELETE FROM CountryLanguage WHERE CountryCode = OLD.Code; -> END // Query OK, 0 rows affected (0.18 sec)

mysql> DELIMITER ;

El cambio de delimitador es necesario en este script porque el disparador requiere una sentencia compuesta para ejecutar dos sentencias separadas cuando se activa el disparador. El cambio de delimitador no es necesario en la mayor parte de los disparadores debido a la simplicidad de la mayora que se crean en el servidor. Este disparador acta como un borrado en cascada para la tabla Country en los pases City y CountryLanguage. Un borrado en cascada asegura que los registros que se han borrado en una tabla, tambin provoquen que se borren los registros asociados a otras tablas conectadas. Esto asegura que no haya registros perdidos en la base de datos y contine la integridad de datos. Este es un uso excelente de los

Apndice B

disparadores en motores de almacenamiento que no soportan esta habilidad de forma natural. 3. Revisar el nmero de registros tanto en City como CountryLanguage, que estn asociados con 'Philippines' (PHL).

mysql> SELECT COUNT(*) FROM City WHERE CountryCode = 'PHL'; mysql> SELECT COUNT(*) FROM CountryLanguage WHERE CountryCode = 'PHL';

4. Eliminar 'Philippines' de la tabla Country.

mysql> DELETE FROM Country WHERE Code = 'PHL';

5. Revisar

de

nuevo

el

nmero

de

registros

tanto

en

City

como

CountryLanguage, que estn asociados con 'Philippines' (PHL).

mysql> SELECT COUNT(*) FROM City WHERE CountryCode = 'PHL'; mysql> SELECT COUNT(*) FROM CountryLanguage WHERE CountryCode = 'PHL';

Si todo ha ocurrido segn lo planeado, los campos de las tablas City y CountryLanguage que estaban asociados con Philipina (PHL) no estarn disponibles. Si el resultado para las sentencias de arriba est vaco, significa que el disparador ins_pais ha funcionado correctamente. 6. Crear un disparador sobre la tabla Country para que con cada UPDATE de un cdigo de pas, las tablas City y CountryLanguage cambien apropiadamente.

mysql> DELIMITER // mysql> CREATE TRIGGER act_pais AFTER UPDATE ON Country -> FOR EACH ROW -> BEGIN -> UPDATE City SET CountryCode=NEW.Code WHERE CountryCode=OLD.Code; -> UPDATE CountryLanguage SET CountryCode=NEW.Code WHERE CountryCode=OLD.Code; -> END // Query OK, 0 rows affected (0.18 sec)

mysql> DELIMITER ;

Este disparador acta como una actualizacin en cascada para la tabla Country en las tablas City y CountryLangauge. Una actualizacin en cascada asegura que los

Apndice B

registros en una tabla que se han actualizado tambin provoquen que se modifiquen los registros asociados en las tablas conectadas. Esto asegura que no haya registros desconectados en la base de datos y contine la integridad de datos. Esto es un excelente uso de los disparadores en aquellos motores de almacenamiento que no soportan esta habilidad de forma natural. 7. Revisar el nmero de registros tanto en City como CountryLanguage, que estn asociados con 'New Zealand' (NZL).

mysql> SELECT COUNT(*) FROM City WHERE CountryCode = 'NZL'; mysql> SELECT COUNT(*) FROM CountryLanguage WHERE CountryCode = 'NZL';

8. Cambiar el cdigo de pas de 'New Zealand' a NEW.

mysql> UPDATE Country SET Code = 'NEW' WHERE Code = 'NZL';

9. Revisar

de

nuevo

el

nmero

de

registros

tanto

en

City

como

CountryLanguage, que estn asociados con 'New Zealand', usando el antiguo CountryCode (NZL).

mysql> SELECT COUNT(*) FROM City WHERE CountryCode = 'NZL'; mysql> SELECT COUNT(*) FROM CountryLanguage WHERE CountryCode = 'NZL';

El resultado para estas sentencias debera estar vaco. Esto es debido al disparador act_pais, que modifica CountryCode en las tablas City y CountryLanguage cuando se produce un cambio en la tabla Country. 10. Revisar de nuevo el nmero de registros tanto en City como

CountryLanguage, que estn asociados con 'New Zealand' pero usar ahora el nuevo CountryCode (NEW).

mysql> SELECT COUNT(*) FROM City WHERE CountryCode = 'NEW'; mysql> SELECT COUNT(*) FROM CountryLanguage WHERE CountryCode = 'NEW';

El mismo nmero de registros debe aparecer aqu que en el paso 7. Esto es debido a que el disparador act_pais asegura que los registros en la tabla City y Country que tienen un CountryCode igual a NZL, se actualizaron para reflejar el cambio a NEW.

Apndice B

11. Crear disparadores sobre la tabla City para garantizar que la poblacin es un mltiplo de 1000 (antes del INSERT y antes del UPDATE).

mysql> CREATE TRIGGER City_ai BEFORE INSERT ON City -> FOR EACH ROW SET NEW.Population = ROUND(NEW.Population,-3); mysql> CREATE TRIGGER City_aa BEFORE UPDATE ON City -> FOR EACH ROW SET NEW.Population = ROUND(NEW.Population,-3);

CAPTULO 20: MOTORES DE ALMACENAMIENTO. Cuestionario. 1. Si se crea una tabla usando una opcin ENGINE= motor_de_almacenamiento para especificar explcitamente el motor de almacenamiento, el servidor MySQL crea la tabla usando el motor de defecto. 2. Enumere los tres motores de almacenamiento ms usados: MyISAM, InnoDB y MEMORY. 3. Cmo se puede desactivar el motor de almacenamiento MyISAM? a. 4. El motor de almacenamiento MyISAM no puede desactivarse.

Ante el bloqueo a nivel de tablas, cmo se comporta por defecto el servidor? b. Las peticiones de escritura tienen mayor prioridad que las peticiones de lectura.

5.

Qu sentencias son verdaderas para las tablas InnoDB? a. El espacio de tablas consisten en uno o ms archivos que son archivos normales o particiones raw. El espacio de tablas compartido puede contener ms de un archivo. Siempre existe un espacio de tablas compartido, aunque InnoDB est configurado para usar un espacio de tablas por cada tabla. En ese caso, el nmero de archivos

Apndice B

de espacios de tabla es igual al nmero de tablas InnODB que se crearon despus de arrancar el servidor con esta opcin, ms, al menos, un archivo ms para el espacio de tablas compartido. Las tablas que se crearon en el espacio de tablas compartido antes de habilitar la opcin de usar un espacio de tablas por tabla, continuarn en el espacio de tablas compartido. 6. Qu tipo de mtodos de bloqueo usa MyISAM? a. 7. Bloqueo a nivel de tabla. se usa InnoDB, qu pasa si ocurre un abrazo mortal

Cuando

(interbloqueo)? En la mayora de los casos, InnoDB detectar el interbloqueo (abrazo mortal). En ese caso, terminar una de las transacciones involucradas. Cuando ocurre esto, se intenta deshacer la transaccin que ha modificado el menor nmero de filas. Si el abrazo mortal no se detecta, las transacciones acabarn por obtener un time out e InnoDB las deshar por su cuenta. 8. Cmo puede definirse el nivel de aislamiento de transacciones en SERIALIZE al momento del arranque del servidor? Se pueden poner estas lneas en un archivo de opciones:

[mysqld] Transaction-isolation = SERIALIZE

Alternativamente, se puede indicar esta opcin a travs de una lnea de comandos:

shell> mysqld --transaction-isolation=serialize

Apndice B

9.

La sentencia SQL SELECT . . . FOR UPDATE tiene sentido para un motor de almacenamiento transaccional como InnoDB pero no lo tiene para un motor no transaccional. Verdadero o falso? Verdadero. SELECT FOR UPDATE se usa para seleccionar un conjunto de filas que se pretende actualizar. Tiene sentido para InnoDB, que permite bloquear filas de forma individual. No tiene sentido para el motor MyISAM, que bloquea la tabla entera aunque slo se actualicen algunas de sus filas.

10. De acuerdo al siguiente listado de la sesin, parece que la consulta SELECT excedi dos minutos para ser ejecutada. Cul es la razn ms probable de que haya ocurrido eso?

mysql> INSERT DELAYED INTO City (ID,Name) VALUES (20000, -> 'Delayne'); Query OK, 1 row affected (#.## sec)

mysql> SELECT ID, Name FROM City WHERE ID = 20000; +-------+---------+ | ID | Name |

+-------+---------+ | 20000 | Delayne | +-------+---------+ 1 row in set (2 min 5.61 sec)

Lo ms probable es que hubiera un bloqueo en la tabla, obtenido por otro cliente. Slo cuando ese cliente libere el bloqueo, se ejecutar su sentencia INSERT DELAYED. Despus de esto, la sentencia SELECT se ejecutar. Sin informacin adicional, se puede asumir que el bloqueo dur, al menos 2 minutos y 5 segundos. Prctica adicional. 1. Crear una copia de la tabla Country que contenga las siguientes columnas: Code (cdigo), Name (nombre) y Continent (continente) de todos los pases de Norteamrica.

mysql> CREATE TABLE norte_america ENGINE=memory -> SELECT Code,Name,Continent FROM Country -> WHERE Continent='North America'; Query OK, 37 rows affected (0.06 sec) Records: 37 Duplicates: 0 Warnings: 0

Apndice B

2. Crear otra tabla MEMORY que contenga las mismas columnas pero ahora de los pases de Surmerica.

mysql> CREATE TABLE sur_america ENGINE=memory -> SELECT Code,Name,Continent FROM Country -> WHERE Continent=South America'; Query OK, 14 rows affected (0.06 sec) Records: 14 Duplicates: 0 Warnings: 0

3. Verificar que las tablas fueron creadas con los motores de almacenamiento correctos.

mysql> SHOW CREATE TABLE norte_america\G *************************** 1. row *************************** Table: norte_america Create Table: CREATE TABLE `norte_america` ( `Code` char(3) NOT NULL DEFAULT '', `Name` char(52) NOT NULL DEFAULT '', `Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL DEFAULT 'Asia' ) ENGINE=MEMORY DEFAULT CHARSET=latin1 1 row in set (0.00 sec)

mysql> SHOW CREATE TABLE sur_america\G *************************** 1. row *************************** Table: sur_america Create Table: CREATE TABLE `sur_america` ( `Code` char(3) NOT NULL DEFAULT '', `Name` char(52) NOT NULL DEFAULT '', `Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL DEFAULT 'Asia' ) ENGINE=MEMORY DEFAULT CHARSET=latin1 1 row in set (0.00 sec)

4. Verificar el directorio de datos para ver qu archivos estn contenidos en las tablas. Los datos deben estar en la ruta del directorio de instalacin del servidor, tal y como: C:/<directorio_instalacin>/data/world/<archivos>.frm

Apndice B

5. Cambiar el motor de almacenamiento de la nueva tabla a MyISAM y ver de nuevo el directorio de datos.

mysql> ALTER TABLE norte_america ENGINE=MyISAM; Query OK, 37 rows affected (0.11 sec) Records: 37 Duplicates: 0 Warnings: 0

mysql> ALTER TABLE sur_america ENGINE=MyISAM; Query OK, 14 rows affected (0.11 sec) Records: 14 Duplicates: 0 Warnings: 0

CAPTULO 21: OPTIMIZACIN. Cuestionario. 1. Bajo qu circunstancias la adicin de ndices a una tabla hace ms lentas las operaciones sobre la tabla? Las operaciones de insertar, borrar y actualizar se ralentizarn cuando la tabla tenga ndices, ya que estas operaciones requieren actualizar los ndices tambin. 2. La indexacin mejora solo el rendimiento de las consultas SELECT y deteriora el rendimiento de las consultas que modifican datos. Es esto verdadero? Los ndices no slo pueden ayudar a aumentar la velocidad de las consultas, sino que tambin mejoran las sentencias UPDATE y DELETE. Esto ocurre porque la indexacin puede ayudar al servidor a encontrar ms rpidamente las filas a actualizar o borrar. Por otro lado, los ndices disminuirn la velocidad de las sentencias UPDATE y DELETE porque no slo debe actualizar los datos originales, sino tambin los ndices.

Apndice B

3. Para los propsitos de un usuario en particular, no importa si una consulta le devuelve un resultado en un segundo o en un minuto, as que no importa la indexacin. Hay alguna objecin con respecto a esta declaracin? Aunque no importe la velocidad de las consultas, los ndices que ayudan a ejecutar ms rpidamente las consultas reducen el tiempo que las tablas permanecen bloqueadas, as como el uso de recursos de la mquina. Esto mejora el rendimiento de las consultas para otros clientes. 4. Cules son las principales razones para no indexar las columnas de una tabla? Si nunca se hace referencia a una columna en comparaciones (WHERE, ORDER BY, GROUP BY) no hay necesidad de indexar esa columna. Es ms, si una columna contiene slo unos pocos valores distintos, un ndice no mejorar la velocidad de las consultas. 5. A continuacin, se muestra un extracto de la definicin de la tabla Country:

mysql> DESCRIBE Country\G ... *************************** 3. row *************************** Field: Continent Type: enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') Null: NO Key: Default: Asia Extra: *************************** 4. row *************************** ...

Si la columna Continent tuviera una clave primaria, cuntas columnas podran existir? Cambiara la situacin si tuviera una clave nica? Si la columna Continent de tipo ENUM tuviera una clave primaria, podra contener 8 filas (los siete nombres diferentes ms la cadena vaca que se inserta cuando ocurre un error). La columna est declarada como NOT NULL, as que la situacin es diferente cuando se usa una clave nica. Si no fuese as, entonces la columna contendra un nmero arbitrario de filas, las cuales la mayora seran valores nulos.

Apndice B

6. Qu se tendra que considerar al acortar lo mximo posible los valores de los ndices? El valor del prefijo de un ndice debe contener la misma cantidad de valores nicos que los valores originales. 7. Cul es la sentencia para crear un ndice de cinco caracteres de longitud en la columna Name de la tabla City? Puedes usar cualquier de las siguientes sentencias para crear el ndice:

mysql> CREATE INDEX Name ON City(Name(5)); mysql> ALTER TABLE City ADD INDEX(Name(5));

8. Cules son las principales razones por las que el uso de la clusula LIMIT puede ayudar a mejorar el rendimiento de las consultas? Cuando se usa LIMIT, el servidor necesita devolver menos informacin al cliente. Otra razn por la que LIMIT puede aumentar la velocidad de las consultas es que algunas ordenaciones de filas terminan ms rpido cuando se combinan con esta clusula. 9. Qu podra agilizar las operaciones de insercin de datos? Se podra usar inserciones de varias filas en lugar de inserciones de filas individuales. LOAD DATA INFILE se ejecuta incluso ms rpido que cualquier sentencia INSERT que inserte la misma cantidad de filas. Para las tablas InnoDB, se pueden agrupar las inserciones en una transaccin, para que InnoDB vuelque los cambios slo cuando la transaccin finalice en vez de por cada fila insertada. Si se est pensando en reemplazar filas usando DELETE e INSERT, se podra usar la extensin de MySQL REPLACE que funciona ms rpido.