Implementacion del lenguaje SQL en MS-JET y otras B.D.

Este documento recoge mis apuntes personales tomados en un curso de autoformaci贸n sobre el lenguaje SQL. No pretende ser un documento exhaustivo ni contemplar todas las variantes del lenguaje, pero puede servir de gu铆a de referencia para el que este empezando.

脥ndice de contenidos

 

Selecci贸n de datos (SELECT)

SELECT * FROM Tabla [WHERE Condici贸n]

SELECT Columna1 [as Alias1], Columna2 [as Alias2],鈥︹ FROM tabla [WHERE Condici贸n]

SELECT Columna1 Alias1, Columna2 Alias2,鈥.. (*1)

SELECT Columna1 = Alias1, Columna2 = Alias2,鈥︹ (*1)

SELECT DISTINCT Columna1 FROM tabla [WHERE Condici贸n]

Selecciona solo los valores distintos de Columna1. (Si valores de Columna1 son 1,2,2,3 el SELECT solo devolver谩 1,2,3)

SELECT Columna1, 鈥楥onstante鈥, Columna2 FROM tabla [WHERE Condici贸n]

Crea una selecci贸n con 3 columnas, fijando el valor de la 2陋 columna como 鈥楥onstante鈥.

SELECT Columna1, Columna2鈥. INTO NuevaTabla [IN BaseDatosExterna] FROM Tabla1 [WHERE Condicion]
Crea una tabla nueva con las columnas y registros seleccionados de la tabla origen. La clausula IN permite crear la tabla nueva en una base de datos externa (que no sea la propia)

 

Operadores:

Numericos:

Alfanumericos

Logicos

Agrupamiento

Otros

 

Funciones

Acumulaci贸n/Agrupaci贸n

Fecha/Hora

Aritm茅ticas

Alfanumericas

Conversi贸n

Otras funciones

 

Clausulas

WHERE

ORDER BY

GROUP BY

HAVING

 

 

Uni贸n de tablas

Ejemplos con estas dos tablas:

Tabla PROD:

Cod

Descr

Precio

1

Producto1

100

2

Producto2

200

3

Producto3

300

4

Producto4

400

Tabla ORD:

CodOrden

CodProd

Cant

901

1

5

902

3

7

903

7

3

904

3

4


SELECT Ord.CodOrden, Prod.Cod, Prod.Descr, Ord.Cant FROM Prod, Ord;

Cruza ambas tablas dando como resultado una fila por cada combinaci贸n de registros de ambas tablas. Es decir que si una tabla tiene 4 registros y la otra otros 4, el resultado del select dar谩 16 filas (4x4)

Resultado del Select

CodOrden

Cod

Descr

Cant

901

1

Producto1

5

901

2

Producto2

5

901

3

Producto3

5

901

4

Producto4

5

902

1

Producto1

7

902

2

Producto2

7

902

3

Producto3

7

902

4

Producto4

7

903

1

Producto1

3

鈥.

鈥.

鈥.

鈥.

SELECT Ord.CodOrden, Prod.Cod, Prod.Descr, Ord.Cant FROM Prod, Ord

WHERE Prod.Cod = 3;


Da como resultado los elementos que cumplen la condicion especificada en la clausula WHERE

CodOrden

Cod

Descr

Cant

901

3

Producto3

5

902

3

Producto3

7

903

3

Producto3

3

904

3

Prodcuto3

4

WHERE Prod.Cod > 3;

Da como resultado los elementos que cumplen la condicion especificada en la clausula WHERE, que puede ser cualquiera menos "="

CodOrden

Cod

Descr

Cant

901

4

Producto4

5

902

4

Producto4

7

903

4

Producto4

3

904

4

Prodcuto4

4

SELECT Ord.CodOrden, Prod.Cod, Prod.Descr, Ord.Cant FROM Ord
JOIN Prod ON Ord.CodProd = Prod.Cod;


Da como resultado los elementos que tienen un valor comun en una columna de cada tabla.

CodOrden

Cod

Descr

Cant

901

1

Producto1

5

902

3

Producto3

7

904

3

Producto3

4

 

SELECT Ord.CodOrden, Prod.Cod, Prod.Descr, Ord.Cant FROM Ord
RIGHT OUTER JOIN Prod ON Ord.CodProd = Prod.Cod;

Devuelve el cojunto completo de valores de la tabla de la derecha ("prod" en este caso), dejando nulas las columnas de tabla de la izquierda que no cumplen la condicion.

Resultado del Select

CodOrden

Cod

Descr

Cant

901

1

Producto1

5

 

2

Producto2

 

902

3

Producto3

7

904

3

Producto3

4

 

4

Prodcuto4

 

 

Devuelve el cojunto completo de valores de la tabla de la izquierda ("ord" en este caso), dejando nulas las columnas de tabla de la derecha que no cumplen la condicion.

Resultado del Select

CodOrden

Cod

Descr

Cant

901

1

Producto1

5

902

3

Producto3

7

903

 

 

3

904

3

Producto3

4

 

 

 

Sub-Queries

Una Sub-query es una query cuyo resultado es pasado como argumento a otra query.

Ejemplo:

 

SELECT * FROM Ord

WHERE CodProd = (SELECT Cod FROM Prod

WHERE Descr = 'Producto3');

Devuelve las ordenes correspondientes al 鈥楶roducto3鈥, sin necesidad de saber el codigo del producto.

Resultado del Select

CodOrden

CodProd

Cant

902

3

7

904

3

4

Y si quisieramos obtener tambien la descripcion del producto entonces podriamos usar:

SELECT Ord.CodOrden, Ord.CodProd, Prod.Descr, Ord.Cant FROM Ord, Prod

WHERE Ord.CodProd = Prod.Cod

AND Ord.CodProd = (SELECT Cod FROM Prod

WHERE Descr = 'Producto3');

 

Resultado del Select

CodOrden

CodProd

Descr

Cant

902

3

Producto3

7

904

3

Producto3

4

 

Esto solo funciona si la subquery (SELECT Cod FROM Prod WHERE Descr = 'Producto3') solo devuelve una fila. P.E. si hubieramoss usado SELECT Cod FROM Prod WHERE Descr like 'Producto%' el select daria error ya que devolveria 4 filas (Producto1, Producto2,鈥.)

Y podriamos complicarlo mas, por ejemplo para averiguar las ordenes cuyo importe este por encima de la media.

SELECT Ord.CodOrden, Ord.CodProd, Prod.Descr, Ord.Cant * Prod.Precio AS Total FROM Ord,Prod

WHERE Ord.CodProd = Prod.Cod

AND Ord.Cant * Prod.Precio > (SELECT AVG(Ord.Cant * Prod.Precio) FROM Ord, Prod

WHERE Ord.CodProd = Prod.Cod);

Resultado del Select

CodOrden

CodProd

Descr

Total

902

3

Producto3

2100

 

Sub-queries anidados

Un subquery anidado es un query incrustado en otro query.

Ejemplo:

SELECT * FROM Ord

WHERE Ord.CodProd IN (SELECT Cod FROM Prod

WHERE Precio <= 300);

Selecciona las ordenes de productos cuyo precio es inferior o igual a 300

Resultado del Select

CodOrden

CodProd

Cant

901

1

5

902

3

7

904

3

4

Un Subquery tambien puede ponerse en una clausual GROUP BY鈥AVING

Ejemplo:

SELECT CodProd, SUM(Cant) AS NroVentas FROM Ord

GROUP BY CodProd

HAVING SUM(Cant) > (SELECT AVG(Cant) FROM Ord);

Selecciona los productos cuyo numero de ventas totales (SUM) es superior a la media (AVG) de ventas de todos los productos.

Resultado del Select

CodProd

NroVentas

1

5

3

11

 

Sub-queries correlacionados

Los subqueries pueden hacer referencias externas lo que provoca que se comporten de manera parecida a un "join".

Por Ejemplo:

SELECT * FROM Ord

WHERE (SELECT Descr FROM Prod

WHERE Ord.CodProd = Prod.Cod) = 'Producto3';

Es equivalente a:

SELECT Ord.CodOrden, Ord.CodProd, Ord.Cant FROM Ord, Prod

WHERE Ord.CodProd = Prod.Cod

AND Prod.Descr = 'Producto3';

En ambos casos el resultado del Select es:

CodOrden

CodProd

Cant

902

3

7

904

3

4

 

La palabra clave EXISTS

EXISTS toma un subquery como argumento y devuelve "verdadero" si el subquery devuelve algo y "falso" si no devuelve nada.

Por ejemplo:

SELECT * FROM Prod

WHERE EXISTS (SELECT * FROM Prod

WHERE Prod.Cod = 3);

Devolver谩 la tabla "Prod" entera:

Cod

Descr

Precio

1

Producto1

100

2

Producto2

200

3

Producto3

300

4

Producto4

400

Ya que EXISTS (SELECT * FROM Prod WHERE Prod.Cod = 3) devuelve "verdadero" para cada una de las filas resultantes del SELECT * FROM Prod

Y por otra parte:

SELECT * FROM Prod

WHERE EXISTS (SELECT * FROM Prod

WHERE Prod.Cod = 9);

No devolver谩 datos, ya que EXISTS (SELECT * FROM Prod WHERE Prod.Cod = 3) devuelve "falso"

Y si se utiliza EXISTS en un query correlacionado, este es evaluado en cada caso implicado en la correlacion. Asi, por ejemplo para buscar los productos que tiene alguna orden asociada se puede usar:

SELECT Cod, Descr FROM Prod

WHERE EXISTS (SELECT * FROM Ord

WHERE Ord.CodProd = Prod.Cod);

Que devolver谩:

Cod

Descr

1

Producto1

3

Producto3

 

Las palabras clave ANY y SOME

Su funcion es identica y puede usarse tanto una como otra.

Comparan el resultado del subquery con cada una de las filas del query, devolviendo "verdadero" por cada fila del query que tienen un resultado en el subquery.

Asi P.E. tenemos otra manera de buscar los productos que tienen alguna orden asociada:

SELECT Cod, Descr FROM Prod

WHERE Cod = ANY (SELECT CodProd FROM Ord);

 

Que tambi茅n devolver谩:

Cod

Descr

1

Producto1

3

Producto3

Esto puede parecer igual que el resultado obtenido usando "IN" (SELECT Cod, Descr FROM Prod WHERE Cod IN (SELECT CodProd FROM Ord);). La diferencia estriba que "ANY" puede ser usado con otros operadores distintos de "=", tales como ">", "<", "<>", etc.

 

 

 

Inserci贸n de datos (INSERT)

INSERT鈥.VALUES

INSERT鈥.SELECT


Actualizaci贸n de datos (UPDATE)

Borrado de datos (DELETE)

Creaci贸n de una base de datos (CREATE DATABASE)

 

Creaci贸n de una tabla (CREATE TABLE)

CREATE TABLE Clientes (Nombre TEXT, Apellido TEXT, FechNac DATETIME
CONSTRAINT Indice UNIQUE (Nombre, Apellido, FechNac));

CREATE TABLE Clientes
(Codigo INTEGER CONSTRAINT ClavePrincipal PRIMARY KEY,
Nombre TEXT, Apellido TEXT);

Modificaci贸n de la estructura de una tabla (ALTER TABLE)

ALTER TABLE Prod ADD CONSTRAINT NuevaClave PRIMARY KEY (Cod);

ALTER TABLE Prod DROP Precio;

ALTER TABLE Prod DROP CONSTRAINT NuevaClave;

Eliminaci贸n de una tabla (DROP TABLE)

 

Eliminaci贸n de una base de datos (DROP DATABASE)

Creacion de una vista (CREATE VIEW) (*1)

CREATE VIEW NombreView [(Columna1, Columna2,鈥)] AS
SELECT 鈥.. FROM 鈥..;

 

Eliminaci贸n de una vista (DROP VIEW) (*1)

DROP VIEW NombreView;

 

Creacion de un sinonimo (CREATE SYNONYM) (*1)

CREATE [PUBLIC] SYNONYM [schema.]synonym FOR [schema.]object[@dblink] 

Eliminaci贸n de un sin贸nimo (DROP SYNONYM) (*1)

DROP [PUBLIC] SYNONYM synonym_name;

 

Creacion de un 铆ndice (CREATE INDEX)

El formato gen茅rico de esta sentencia es CREATE INDEX NombreIndice ON TablaX (Columna1, Columna2,鈥); pero varia mucho seg煤n el gestor de B.D.

En el caso de MS-Jet el formato es:

CREATE [UNIQUE] INDEX Indice

ON TablaX (Campo1 [ASC / DESC][, Campo2 [ASC / DESC]鈥..]

[WITH {PRIMARY, DISALLOW NULL, IGNORE NULL}];

 

Eliminacion de un indice (DROP INDEX)

 

DROP INDEX NombreIndex;

DROP INDEX NombreIndex ON TablaX;

 

 

Trabajo con transacciones

La implementacion es muy diferente de un gestor de B.D. a otro. Esta es la sintaxis usada por SQL-Server, por poner un ejemplo.

BEGIN TRANSACTION NombreTransacci贸n; para iniciar una transaccion

COMMIT TRANSACTION NombreTransacci贸n; para finalizar una transaccion confirmando los cambios.

ROLLBACK TRANSACTION NombreTransacci贸n; para finalizar una transaccion cancelando los cambios.

SAVE NombreTransaccion NombreSavePoint; establece un "SavePoint"

ROLLBACK TRANSACTION NombreSavePoint; deshace los cambios realizados desde el "SavePoint" especificado.

Y este podria ser un ejemplo real.

BEGIN TRANSACTION

UPDATE Balances SET Curr_Bal = 25000 WHERE Account_ID = 5

SAVE TRANSACTION save_it

DELETE FROM Balances WHERE Account_ID = 5

ROLLBACK TRANSACTION save_it

COMMIT TRANSACTION

GO

Las B.D. MS-Access no soportan el trabajo con transacciones.

 

 

Seguridad de la base de datos

Los sistemas de base de datos mas sencillos, MS-Access por ejemplo, no soportan practicamente ningun tipo de seguridad. Los ejemplos siguientes estan basados en la implementacion de Personal Oracle 7.

Creacion de usuarios:

CREATE USER user
IDENTIFIED {BY password | EXTERNALLY}
[DEFAULT TABLESPACE tablespace]
[TEMPORARY TABLESPACE tablespace]
[QUOTA {integer [K|M] | UNLIMITED} ON tablespace]
[PROFILE profile];

Modificacion de usuarios

ALTER USER user
[IDENTIFIED {BY password | EXTERNALLY}]
[DEFAULT TABLESPACE tablespace]
[TEMPORARY TABLESPACE tablespace]
[QUOTA {integer [K|M] | UNLIMITED} ON tablespace]
[PROFILE profile] [DEFAULT ROLE { role [, role] ... | ALL [EXCEPT role [, role] ...] | NONE}];

Eliminacion de usuarios:

DROP USER user_name [CASCADE];

Asignacion de "Roles". Un "Rol" es un privilegio o conjunto de privilegios que permiten a un usuario realizar ciertas funciones en la base de datos.

Asignacion de "Roles" a usuarios

GRANT role TO user [WITH ADMIN OPTION];

Revocaci贸n de "Roles" a usuarios:

REVOKE role FROM user;

Algunos de los "roles" existentes son:

Asignacion de privilegios al usuario. Permiten asignar los permisos que tienen los usuarios sobre los objetos de la B.D.

Se pueden asignar privilegios de sistema y privilegios de objeto

Los privilegios de sistema afectan a todo el sistema y se asignan con:

GRANT system_privilege TO {user_name | role | PUBLIC} [WITH ADMIN OPTION];

Los privilegios de objeto afectan solo al objeto en cuestion y se asignan con:

GRANT {object_priv | ALL [PRIVILEGES]} [ (column
[, column]...) ]
[, {object_priv | ALL [PRIVILEGES]} [ (column
[, column] ...) ] ] ...
ON [schema.]object
TO {user | role | PUBLIC} [, {user | role | PUBLIC}] ...
[WITH GRANT OPTION]

 

y se revocan con:

REVOKE {object_priv | ALL [PRIVILEGES]}
[, {object_priv | ALL [PRIVILEGES]} ]
ON [schema.]object
FROM {user | role | PUBLIC} [, {user | role | PUBLIC}]
[CASCADE CONSTRAINTS]

Y ahora un caso practico:

Crear una tabla

CREATE TABLE SALARIES (NAME CHAR(30), SALARY NUMBER, AGE NUMBER);

Crear dos usuarios:

CREATE USER Jack IDENTIFIED BY Jack;

CREATE USER Jill IDENTIFIED BY Jill;

Asignarles los roles:

GRANT CONNECT TO Jack;

GRANT RESOURCE TO Jill;

Cargar la tabla con los siguientes datos:

NAME SALARY AGE

---- ------ ---

JACK 35000 29

JILL 48000 42

JOHN 61000 55

Hacer que Jack solo pueda hacer SELECTs

GRANT SELECT ON SALARIES TO Jack;

Y que Jill puede hacer SELECTs y ademas pueda actualizar la columna "Salary".

GRANT SELECT, UPDATE(SALARY) ON SALARIES TO Jill;

Ahora bien, para que puedan acceder a la tabla "Salaries" deberan referenciarla (cualificarla) con el nombre de usuario propietario de la tabla (el que la cre贸). P.E. SELECT * FROM Bryan.SALARIES; suponiendo que el usuario que el propietario de la tabla sea "Bryan".

Para no tener que cualificar la tabla cada vez con el nombre de su propietario se puede crear una view. P.E.: CREATE VIEW SALARY_VIEW AS SELECT FROM Bryan.SALARIES;

Otra posibilidad seria que un usuario con rol DBA creara un sinonimo publico con CREATE PUBLIC SYNONYM SALARY FOR SALARIES;

Tambien se pueden usar views para controlar los datos a los que los usuarios pueden accecer. P.E. para evitar que Jack pueda mirar los salarios de otras personas:

CREATE VIEW JACK_SALARY AS SELECT * FROM BRYAN.SALARIES
WHERE NAME = 'JACK';

GRANT SELECT ON JACK_SALARY TO Jack;

Normalmente un usuario no puede pasar sus privilegios a otros usuarios, salvo que estos le hayan sido concedidos especificando la clausula WITH GRANT OPTION. Asi P.E.

GRANT SELECT, UPDATE(SALARY) ON Bryan.SALARIES TO JILL 
WITH GRANT OPTION;

Permitira que Jill pueda pasar estos privilegios a otros usuarios.

 

Tablas temporales

Son tablas de trabajo que solo existen hasta que el usuario se desidentifica o finaliza la conexi贸n con la B.D.

La implementacion difiere entre los diferentes gestores de B.D. y algunos no lo soportan (MS-Access P.E.)

Estos ejemplos estan basados en la implementaci贸n del SQL-Server.

CREATE TABLE #albums (artist CHAR(30), album_name CHAR(50), media_type INT) ;

El car谩cter # delante del nombre indica que se trata de una tabla temporal. Las

Otra posibilidad es crearla con:

CREATE TABLE tempdb..albums (artist CHAR(30), album_name CHAR(50), media_type INT) ;

Con lo cual la tabla temporal tambien es creada en B.D. "tempdb", pero no se elimina automaticamente al desidentificarse el usuario, sino que este tendra que hacerlo expresamente con un DROP TABLE. (Tambi茅n todas las tablas temporales se borran al rearrancar el SQL-Server)

Las tablas temporales son normalmente usadas para almacenar el resultado de consultas complejas que puede ser usado en otras consultas.

 

Cursores

Los cursores permiten seleccionar un grupo de datos, moverse a traves del grupo de registros (recordset) y examinar individualmente los datos a los que apunta el cursor.

La implementacion difiere entre los diferentes gestores de B.D. y algunos no lo soportan

Estos ejemplos estan basados en la implementaci贸n del SQL-Server (Transact-SQL).

DECLARE NombreCursor CURSOR
     FOR sentencia_select
     [FOR {READ ONLY | UPDATE [OF lista_nombres_columnas]}]

Por ejemplo: CREATE Artists_Cursor CURSOR FOR SELECT * FROM Artists; crea un cursor que contiene todos los registros de la tabla Artists, pero antes de usarlo hay que abrirlo con:

OPEN Artists_Cursor;

Una vez abierto ya puede ser usado para moverse por las filas resultantes de la consulta:

FETCH cursor_name [INTO fetch_target_list];

Cada vez que se hace un FETCH el cursor avanza a la siguiente fila.

Y a continuacion lo normal seria cerrar el cursor con:

CLOSE Artists_Cursor;

Y liberar la memoria asociada con el:

DEALLOCATE CURSOR Artists_Cursor;

Un ejemplo pr谩ctico que declara unas variables, las carga con los datos de cada una de las filas y las imprime.

DECLARE @name char(30)
DECLARE @homebase char(40)
DECLARE @style char(20)
DECLARE @artist_id int

CREATE Artists_Cursor CURSOR FOR SELECT * FROM Artists

OPEN Artists_Cursor
FETCH Artists_Cursor INTO @name, @homebase, @style, @artist_id
WHILE (@@sqlstatus = 0)
BEGIN
PRINT @name
PRINT @homebase
PRINT @style
PRINT char(@artist_id)
FETCH Artists_Cursor INTO @name, @homebase, @style, @artist_id
END

CLOSE Artists_Cursor

DEALLOCATE CURSOR Artists_Cursor

Los cursores no son objetos de la base de datos sino que residen en memoria.

Creaci贸n y uso de procedimientos almacenados

Los procedimientos almacenados funciones conteniendo agrupaciones de sentencias SQL. Estas funciones son llamadas y ejecutadas como las funciones de C o Visual Basic por ejemplo.

Estos procedimientos estan almacenados como parte de la B.D.

En un entorno cliente-servidor una de las grandes ventajas del uso de procedimientos almacenados es que estos son ejecutados en el servido, transfiriendose al cliente solo los datos resultado de la ejecuci贸n.

Ademas, son guardados en la base de datos ya compilados y optimizados, con lo cual aumenta la velocidad de ejecuci贸n.

La implementacion difiere entre los diferentes gestores de B.D. y algunos no lo soportan

Estos ejemplos estan basados en la implementaci贸n del SQL-Server (Transact-SQL).

Para crear el procedimiento almacenado:

CREATE PROCEDURE procedure_name
     [[(]@parameter_name
         datatype [(length) | (precision [, scale])
         [= default][output]
     [, @parameter_name
         datatype [(length) | (precision [, scale])
         [= default][output]]...[)]]
     [with recompile]
    AS SQL_statements

Y para ejecutarlo:

EXECUTE [@return_status = ]
     procedure_name
     [[@parameter_name =] value |
         [@parameter_name =] @variable [output]...]]
     [with recompile]

Los procedimientos almacenados aceptan parametros de entrada y salida. En este ejemplo se define un procedimiento "Match_Homebase_To_Name" con un parametro de entrada "homebase" y otro de salida "name".

CREATE PROCEDURE Match_Homebase_To_Name @homebase char(40), @name char(30) output
AS
SELECT @name = name FROM ARTISTS WHERE homebase = @homebase

Y se invocaria de la siguiente manera:

DECLARE @return_name char(30)
EXECUTE Match_Homebase_To_Name "Los Angeles", @return_name = @name output
PRINT @name

Como puede esperarse para eliminar un procedimiento almancenado se debe usar DROP

DROP PROCEDURE procedure_name

 

Para modificar un procedimiento almacenado primero hay que eliminar el antiguo. El script SQL usado normalmente en SQL server para hacer esto es:

IF EXISTS (SELECT * FROM SYSOBJECTS WHERE name = "procedure_name")
BEGIN
DROP PROCEDURE procedure_name
END
GO
CREATE PROCEDURE procedure_name
AS
.

.

Los procedimientos almacenados puede ser anidados. Es decir que uno puede llamar a otros y estos a su vez a otros. Pero hay que tener en cuenta que:

 

Dise帽ando y usando Triggers

Un trigger es basicamente un tipo especial de procedimiento almacenado que puede ejecutarse como respuesta a un update, un insert o un delete

La implementacion difiere entre los diferentes gestores de B.D. y algunos no lo soportan

Estos ejemplos estan basados en la implementaci贸n del SQL-Server (Transact-SQL).

CREATE TRIGGER trigger trigger_name
   ON table_name
   FOR {insert, update, delete}
   AS SQL_Statements;

Las acciones ejecutadas en un trigger se ejecutan implicitamente como parte de una transaccion. La secuencia seria:

  1. Se ejecuta un BEGIN TRANSACTION implicito
  2. Tiene lugar el INSERT, DELETE o UPDATE
  3. Se llama al trigger y se ejecutan sus sentencias
  4. El trigger hace ROLL BACK de la transaccion, o se hace un COMMIT implicito de la misma.

En este ejemplo se activa un trigger para los INSERT y UPDATE de la tabla RECORDINGS en el cual se comprueba que no se puedan a帽adir o modificar registros de la tabla para los cuales no exista el codigo (artist_id) del artista en la tabla de artistas.

CREATE TRIGGER check_artists
ON RECORDINGS
FOR INSERT, UPDATE AS
IF NOT EXISTS (select * from ARTISTS, RECORDINGS
where ARTISTS.artist_id = RECORDINGS.artist_id)
BEGIN
PRINT "Illegal Artist_ID!"
ROLLBACK TRANSACTION
END

Restricciones a tener en cuenta:

Los triggers se pueden anidar (dependiendo de la configuracion del gestor de la B.D.). Es decir que la accion tomada dentro de un trigger puede provocar la activacion de otro trigger, y este la otro, etc.

 

SQL embedido

El termino SQL embedido se utiliza para referirse al uso de procedimientos almacenados dentro dentro de un programa de aplicaci贸n.

SQL est谩tico

Las sentencias SQL son includidas directamente en el c贸digo del programa. Este codigo no puede ser modificado en tiempo de ejecuci贸n.

SQL din谩mico

Permite construir la sentencia SQL en tiempo de ejecuci贸n y pasarla al gestor de la B.D. para su ejecuci贸n.

Este ejemplo ilustra el uso del SQL est谩tico en una funcion C.

BOOL Print_Employee_Info (void)
{
int Age = 0;
char Name[41] = "\0";
char Address[81] = "\0";
/* Now Bind Each Field We Will Select To a Program Variable */
#SQL BIND(AGE, Age)
#SQL BIND(NAME, Name);
#SQL BIND(ADDRESS, Address);
/* The above statements "bind" fields from the database to variables from the program.
 After we query the database, we will scroll the records returned
and then print them to the screen */

#SQL SELECT AGE, NAME, ADDRESS FROM EMPLOYEES;

#SQL FIRST_RECORD
if (Age == NULL)
{
     return FALSE;
}
while (Age != NULL)
{
     printf("AGE = %d\n, Age);
     printf("NAME = %s\n, Name);
     printf("ADDRESS = %s\n", Address);
     #SQL NEXT_RECORD
}
return TRUE;

}

(*1) No soportado por MS-JET

Tambi茅n te puede interesar el programa SQL2MDB, para ejecutar archivos .SQL contra bases de datos Access

 
Compartir: Twitter   Facebook   P谩gina principal Mapa del sitio Radio SherlockBuscador Radio Sherlock Terminos de servicio  Privacidad  Cookies