## Seleccionar Tablas

#### Crear una Tabla

Primero, crearemos una de las tablas de nuestro ejemplo. Esta tabla, COFFEES, contiene la información esencial sobre los cafés vendidos en "The Coffee Break", incluyendo los nombres de los cafés, sus precios, el número de libras vendidas la semana actual, y el número de libras vendidas hasta la fecha. Aquí puedes ver la tabla COFFEES, que describiremos más adelante:

COF_NAME | SUP_ID | PRICE | SALES | TOTAL
--- | --- | --- | --- | ---
#### Colombian | 101 | 7.99 | 0 | 0
#### French_Roast | 49 | 8.99 | 0 | 0
#### Espresso | 150 | 9.99 | 0 | 0
#### Colombian_Decaf | 101 | 8.99 | 0 | 0
#### French_Roast_Decaf | 49 | 9.99 | 0 | 0

La columna que almacena el nombre del café es COF_NAME, y contiene valores con el tipo VARCHAR de SQL y una longitud máxima de 32 caracteres. Como utilizamos nombres diferentes para cada tipo de café vendido, el nombre será un único identificador para un café particular y por lo tanto puede servir como clave primaria. La segunda colunma, llamada SUP_ID, contiene un número que identifica al suministrador del café; este número será un tipo INTEGER de SQL. La tercera columna, llamada PRICE, almacena valores del tipo FLOAT de SQL porque necesita contener valores decimales. (Observa que el dinero normalmente se almacena en un tipo DECIMAL o NUMERIC de SQL, pero debido a las diferencias entre controladores de bases de datos y para evitar la incompatibilidad con viejas versiones de JDBC, utilizamos el tipo más estándard FLOAT.) La columna llamada SALES almacena valores del tipo INTEGER de SQL e indica el número de libras vendidas durante la semana actual. La columna final, TOTAL,contiene otro valor INTEGER de SQL que contiene el número total de libras vendidas hasta la fecha.

SUPPLIERS, la segunda tabla de nuesta base de datos, tiene información sobre cada uno de los suministradores:

SUP_ID | SUP_NAME | STREET | CITY | STATE | ZIP
--- | --- | --- | --- | --- | ---
101 | Acme, Inc. | 99 Market Street | Groundsville | CA | 95199
49 | Superior Coffee | 1 Party Place | Mendocino | CA | 95460
150 | The High Ground | 100 Coffee Lane | Meadows | CA | 93966

Las tablas COFFEES y SUPPLIERS contienen la columna SUP_ID, lo que significa que estas dos tablas pueden utilizarse en sentencias SELECT para obtener datos basados en la información de ambas tablas. La columna SUP_ID es la clave primaria de la tabla SUPPLIERS, y por lo tanto, es un identificador único para cada uno de los suministradores de café. En la tabla COFFEES, SUP_ID es llamada clave extranjera. (Se puede pensar en una clave extranjera en el sentido en que es importada desde otra tabla). Observa que cada número SUP_ID aparece sólo una vez en la tabla SUPPLIERS; esto es necesario para ser una clave primaria. Sin embargo, en la tabla COFFEES, donde es una clave extranjera, es perfectamente correcto que haya números duplicados de SUP_ID porque un suministrador puede vender varios tipos de café. Más adelante en este capítulo podremos ver cómo utilizar claves primarias y extranjeras en una sentencia SELECT.

La siguiente sentencia SQL crea la tabla COFFEES. Las entradas dentro de los paréntesis exteriores consisten en el nombre de una columna seguido por un espacio y el tipo SQL que se va a almacenar en esa columna. Una coma separa la entrada de una columna (que consiste en el nombre de la columna y el tipo SQL) de otra. El tipo VARCHAR se crea con una longitud máxima, por eso toma un parámetro que indica la longitud máxima. El parámetro debe estar entre paréntesis siguiendo al tipo. La sentencia SQL mostrada aquí, por ejemplo, específica que los nombres de la columna COF-NAME pueden tener hasta 32 caracteres de longitud:

    CREATE TABLE COFFEES
    	(COF_NAME VARCHAR(32),
     SUP_ID INTEGER,
     PRICE FLOAT,
     SALES INTEGER,
     TOTAL INTEGER)

Este código no termina con un terminador de sentecia de un controlador de base de datos, que puede variar de un controlador a otro. Por ejemplo, Oracle utiliza un punto y coma (;) para finalizar una sentencia, y Sybase utiliza la plabra go. El driver que estamos utilizado proporcionará automáticamente el terminador de setencia apropiado, y no necesitaremos introducirlo en nuestro código JDBC.

Otra cosa que debíamos apuntar sobre las sentencias SQL es su forma. En la sentencia CREATE TABLE, las palabras clave se han imprimido en letras máyusculas, y cada ítem en una línea separada. SQL no requiere nada de esto, estas convenciones son sólo para una fácil lectura. El estándard SQL dice que la palabras claves no son sensibles a las mayúsculas, así, por ejemplo, la anterior sentencia SELECT pude escribirse de varias formas. Y como ejemplo, estas dos versiones son equivalentes en lo que concierne a SQL:

    SELECT First_Name, Last_Name
    FROM Employees
    WHERE Last_Name LIKE "Washington"
    select First_Name, Last_Name from Employees where
    Last_Name like "Washington"

Sin embargo, el material entre comillas si es sensible a las maýusculas: en el nombre "Washington", "W" debe estar en maýuscula y el resto de las letras en minúscula.

Los requerimientos pueden variar de un controlador de base de datos a otro cuando se trada de nombres de identificadores. Por ejemplo, algunos controladores, requieren que los nombres de columna y de tabla seán exactamente los mismos que se crearon en las sentencias CREATE y TABLE, mientras que otros controladores no lo necesitan. Para asegurarnos, utilizaremos mayúsculas para identificadores como COFFEES y SUPPLIERS porque así es como los definimos.

Hasta ahora hemos escrito la sentencia SQL que crea la tabla COFFEES. Ahora le pondremos comillas (crearemos un string) y asignaremos el string a la variable createTableCoffees para poder utilizarla en nuestro código JDBC más adelante. Como hemos visto, al controlador de base de datos no le importa si las líneas están divididas, pero en el lenguaje Java, un objeto String que se extienda más allá de una línea no será compilado. Consecuentemente, cuando estamos entregando cadenas, necesitamos encerrar cada línea entre comillas y utilizar el signo más (+) para concatenarlas:

    String createTableCoffees = "CREATE TABLE COFFEES " +
    		"(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " +
    		"SALES INTEGER, TOTAL INTEGER)";

Los tipos de datos que hemos utilizado en nuestras sentencias CREATE y TABLE son tipos genéricos SQL (también llamados tipos JDBC) que están definidos en la clase java.sql.Types. Los controladores de bases de datos generalmente utilizan estos tipos estándards, por eso cuando llegue el momento de probar alguna aplicación, sólo podremos utilizar la aplicación CreateCoffees.java, que utiliza las sentencias CREATE y TABLE. Si tu controlador utiliza sus propios nombres de tipos, te suministrarermos más adelante una aplicación que hace eso.

Sin embargo, antes de ejecutar alguna aplicación, veremos lo más básico sobre el JDBC.

#### Crear sentencias JDBC

Un objeto Statement es el que envía nuestras sentencias SQL al controlador de la base de datos. Simplemente creamos un objeto Statement y lo ejecutamos, suministando el método SQL apropiado con la sentencia SQL que queremos enviar. Para una sentencia SELECT, el método a ejecutar es executeQuery. Para sentencias que crean o modifican tablas, el método a utilizar es executeUpdate.

Se toma un ejemplar de una conexión activa para crear un objeto Statement. En el siguiente ejemplo, utilizamos nuestro objeto Connection: con para crear el objeto Statement: stmt:

    Statement stmt = con.createStatement();

En este momento stmt existe, pero no tiene ninguna sentencia SQL que pasarle al controlador de la base de datos. Necesitamos suministrarle el metodo que utilizaremos para ejecutar stmt. Por ejemplo, en el siguiente fragmento de código, suministramos executeUpdate con la sentencia SQL del ejemplo anterior:

    stmt.executeUpdate("CREATE TABLE COFFEES " +
    		"(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " +
    		"SALES INTEGER, TOTAL INTEGER)");

Coma ya habíamos creado un String con la sentencia SQL y lo habíamos llamado createTableCoffees, podríamos haber escrito el código de esta forma alternativa:

    stmt.executeUpdate(createTableCoffees);

#### Ejecutar Sentencias

Utilizamos el método executeUpdate porque la sentencia SQL contenida en createTableCoffees es una sentencia DDL (data definition language). Las sentencias que crean, modifican o eliminan tablas son todas ejemplos de sentencias DDL y se ejecutan con el método executeUpdate. Cómo se podría esperar de su nombre, el método executeUpdate también se utiliza para ejecutar sentencias SQL que actualizan un tabla. En la práctica executeUpdate se utiliza más frecuentemente para actualizar tablas que para crearlas porque una tabla se crea sólo una vez, pero se puede actualizar muchas veces.

El método más utilizado para ejecutar sentencias SQL es executeQuery. Este método se utiliza para ejecutar sentencias SELECT, que comprenden la amplia mayoría de las sentencias SQL. Pronto veremos como utilizar este método.

#### Introducir Datos en una Tabla

Hemos visto como crear la tabla COFFEES especificando los nombres de columnas y los tipos de datos almacenados en esas columnas, pero esto sólo configura la estructura de la tabla. La tabla no contiene datos todavía. Introduciremos datos en nuestra tabla una fila cada vez, suministrando la información a almacenar en cada columna de la fila. Observa que los valores insertados en las columnas se listan en el mismo orden en que se declararon las columnas cuando se creó la tabla, que es el orden por defecto.

El siguiente código isnerta una fila de datos con Colombian en la columna COF_NAME, 101 en SUP_ID, 7.99 en PRICE, 0 en SALES, y 0 en TOTAL. (Como acabamos de inaugurar "The Coffee Break", la cantidad vendida durante la semana y la cantidad total son cero para todos los cafés). Al igual que hicimos con el código que creaba la tabla COFFEES, crearemos un objeto Statement y lo ejecutaremos utilizando el método executeUpdate.

Como la sentencia SQL es damasiado larga como para entrar en una sóla línea, la hemos dividido en dos strings concatenándolas mediante un signo más (+) para que puedan compilarse. Presta especial atención a la necesidad de un espacio entre COFFEES y VALUES. Este espacio debe estar dentro de las comillas y debe estar después de COFFEES y antes de VALUES; sin un espacio, la sentencia SQL sería leída erróneamente como "INSERT INTO COFFEESVALUES . . ." y el controlador de la base de datos buscaría la tablaCOFFEESVALUES. Observa también que utilizamos comilla simples alrededor del nombre del café porque está anidado dentro de las comillas dobles. Para la mayoría de controladores de bases de datos, la regla general es alternar comillas dobles y simples para indicar anidación.

    Statement stmt = con.createStatement();
    stmt.executeUpdate(
        "INSERT INTO COFFEES " +
        "VALUES ('Colombian', 101, 7.99, 0, 0)");

El siguiente código inserta una segunda línea dentro de la tabla COFFEES. Observa que hemos reutilizado el objeto Statement: stmt en vez de tener que crear uno nuevo para cada ejecución.

    stmt.executeUpdate("INSERT INTO COFFEES " +
        "VALUES ('French_Roast', 49, 8.99, 0, 0)");

Los valores de las siguientes filas se pueden insertar de esta forma:

    stmt.executeUpdate("INSERT INTO COFFEES " +
        "VALUES ('Espresso', 150, 9.99, 0, 0)");
    stmt.executeUpdate("INSERT INTO COFFEES " +
        "VALUES ('Colombian_Decaf', 101, 8.99, 0, 0)");
    stmt.executeUpdate("INSERT INTO COFFEES " +
        "VALUES ('French_Roast_Decaf', 49, 9.99, 0, 0)");

#### Obtener Datos desde una Tabla

Ahora que la tablaCOFFEES tiene valores, podemos escribir una sentencia SELECT para acceder a dichos valores. El asterisco (*) en la siguiente sentencia SQL indica que la columna debería ser seleccionada. Como no hay claúsula WHERE que limite las columas a seleccionar, la siguiente sentencia SQL seleciona la tabla completa:

    SELECT * FROM COFFEES

El resultado, que es la tabla completa, se parecería a esto:

COF_NAME | SUP_ID | PRICE | SALES | TOTAL
--- | --- | --- | --- | ---
Colombian | 101 | 7.99 | 0 | 0
French_Roast | 49 | 8.99 | 0 | 0
Espresso | 150 | 9.99 | 0 | 0
Colombian_Decaf | 101 | 8.99 | 0 | 0
French_Roast_Decaf | 49 | 9.99 | 0 | 0

El resultado anterior es lo que veríamos en nuestro terminal si introdujeramos la petición SQL directamente en el sistema de la base de datos. Cuando accedemos a una base de datos a través de una aplicación Java, como veremos pronto, necesitamos recuperar los resultados para poder utilizarlos. Veremos como hacer esto en la siguiente página.

Aquí tenemos otro ejemplo de una sentencia SELECT, ésta obtiene una lista de cáfes y sus respectivos precios por libra:

    SELECT COF_NAME, PRICE FROM COFFEES

El resultado de esta consulta se parecería a esto:

COF_NAME | ------------------- | PRICE
--- | --- | ---
Colombian |  | 7.99
French_Roast |  | 8.99
Espresso |  | 9.99
Colombian_Decaf |  | 8.99
French_Roast_Decaf |  | 9.99

La sentencia SELECT genera los nombres y precios de todos los cáfes de la tabla. La siguiente sentencia SQL límita los cafés seleccionados a aquellos que cuesten menos de $9.00 por libra:

    SELECT COF_NAME, PRICE
    FROM COFFEES
    WHERE PRICE < 9.00

El resultado se parecería es esto:

COF_NAME | -------------------- | PRICE
--- | --- | ---
Colombian |  | 7.99
French_Roast |  | 8.99
Colombian Decaf |  | 8.99

Ozito