Sunteți pe pagina 1din 18

INSTITUTO TECNOLÓGICO DE TIJUANA

SUBDIRECCIÓN ACADÉMICA

DEPARTAMENTO DE SISTEMAS Y COMPUTACIÓN

SEMESTRE AGOSTO DICIEMBRE 2012

ING. SISTEMAS COMPUTACIONALES

FUNDAMENTOS DE BASE DE DATOS

SQL (INVESTIGACION - CONCEPTOS)

UNIDAD 6

ZAVALA LOPEZ RAUL ANTONIO - 11210308

M.C. FELMA LIZBETH GONZALEZ FLORES.

12/11/12
Índice
No. Página.

1.- Procedimientos almacenados…………………………………………………………… 1 - 2

2.- Triggers (Disparadores)…………………………………………………………………… 2 - 3

3.- Reglas sintácticas……………………………………………………………………………. 4 - 5

4.- Clave primaria (Primary key)…………………………………………………………… 5 - 6

5. - Clave foránea (Foreing key)…………………………………………………………….. 6 - 8

6. - Restricciones (Check, Unique, Not Null)…………………………………………. 8 - 11

7.- Valores predeterminados (Default values)…………………………………….. 11 - 12

8.- Vistas (Views)………………………………………………………………………………… 12 - 14

9.- Índices (Indexes)……………………………………………………………………………. 14 – 15

10.- Referencias (Bibliografía)……………………………………………………………. 16


Procedimientos almacenados.

Un procedimiento almacenado es un objeto perteneciente a una base de datos, que contiene un


conjunto de instrucciones SQL, tanto de consulta, como de manipulación de datos, como de
control de la secuencia del programa, asociados a un nombre, y que son ejecutados en conjunto.

Puede contener parámetros tanto de entrada como de salida (parámetros pasados por
referencia), así como devolver un valor de retorno.

Son precompilados al ejecutarse por primera vez, y no vuelven a ser compilados con las
subsiguientes ejecuciones, lo que proporciona una cierta mejora en el rendimiento.

No obstante si se desea se puede forzar su recompilación.

Una de las principales ventajas de este tipo de objetos, es que al residir en la propia base de
datos son compartibles por todos los usuarios, pudiendo de esta manera beneficiarse de los
distintos cachés del servidor. Al mismo tiempo al ser código externo a la aplicación puede ser
alterado sin que exista siempre la necesidad de modificar el código de la misma.

Al ser objetos de la base de datos se hallan sujetos a los esquemas de seguridad determinados
por el administrador de la misma:

Existen diversas clases de procedimientos almacenados, entre los que se encuentra los
procedimientos almacenados del sistema, que sirven de herramientas para la realización de
distintas tareas de administración.

Un procedimiento almacenado se crea con la sentencia CREATE PROCEDURE, que debe serla
única dentro de un mismo batch. La creación de un procedimiento almacenado puede ser
realizada bien desde el ISQL_W ,o bien desde la opción Manage Stored Procedures del
Enterprise Manager (SQL Server), o bien desde la propia ventana donde se muestran los objetos
de la base de datos, en el grupo correspondiente a los procedimientos almacenados, dentro de
esta última herramienta.

La sintaxis de dicha instrucción es básicamente la siguiente:

CREATE PROCEDURE Nombre_del_procedimiento [Lista_de_parámetros] AS (Sentencias SQL)[RETURN


[Valor]]

Ejemplo en “SQL SERVER”:

CREATE PROCEDURE uspGetAddress


AS
SELECT * FROM AdventureWorks.Person.Address
GO

1
Un procedimiento almacenado puede devolver un valor de retorno de tipo integer, no nulo,
que puede ser rescatado por el código llamador para tener conocimiento del resultado del
proceso de dicho procedimiento.

Los valores -1 al -99 están reservados por el sistema, así como el 0 que se interpreta como
“finalizado con éxito”.

Si no se proporciona un código definido por el usuario, se utilizan los del sistema. De la misma
forma los definidos por el usuario tienen prioridad sobre los definidos por el sistema.

En caso de producirse varios errores a lo largo de la ejecución del mismo procedimiento, se


devuelve el código cuyo valor absoluto es mayor.

Algunos ejemplos de códigos y sus significados son los siguientes:

Código Significado
-2 Error de tipo de datos
-4 Error de permisos
-5 Error de sintaxis
-13 Base de datos corrupta

Disparadores (Triggers).

Un trigger (Disparador) es un tipo especial de procedimiento almacenado que se ejecuta


automáticamente al intentarse efectuar una modificación de los datos, en la tabla a la que se
encuentran asociados.

Las operaciones que pueden “disparar” un trigger son las correspondientes a las instrucciones
SQL , INSERT , UPDATE y DELETE.

Puede definirse un trigger para cada una de ellas, o bien definir un trigger asociado a una
combinación de las mismas.

La mayor utilidad que se confiere a un trigger, es la de asegurar la integridad referencial o el


cumplimiento de las distintas reglas definidas, si bien estas son operaciones que pueden
delegarse en el propio servidor, mediante las instrucciones y cláusulas de especificación de las
reglas de integridad, definidas durante la creación de las tablas, o añadidas posteriormente.

El hecho de tener algún trigger asociado a una tabla, incide de forma negativa en cuanto al
rendimiento se refiere, si bien la mayor parte del tiempo empleado en su ejecución
corresponde al acceso a las diferentes tablas implicadas en los chequeos de integridad.

2
En relación a la creación de los triggers, las herramientas disponibles son las mismas que en el
caso de los procedimientos almacenados, si bien deberán utilizarse las opciones
correspondientes.
La instrucción que permite la creación de un trigger es: CREATE TRIGGER , y su sintaxis es la
siguiente:

CREATE TRIGGER Nombre_del_Trigger


ON Nombre_de_la_tabla
FOR {INSERT,UPDATE,DELETE}
AS (Sentecias_SQL)

Nombre_del_Trigger : Es el Identificador que determina el nombre del trigger en la base


dedatos y que debe cumplir las reglas de construcción de identificadores en SQL Server.

Nombre_de_la_tabla : Es el Nombre de la tabla sobre la que será ejecutado el trigger, en caso


de ser ésta alterada, en cuanto a datos se refiere.

INSERT
Instrucción de inserción de filas.
UPDATE
Instrucción de actualización de filas.
DELETE
Instrucción de eliminación de filas.

Sentencias_SQL
Cualquier tipo de sentencia SQL, a excepción de las siguientes:
•Cualquier instrucción CREATE
•Cualquier instrucción DROP
•ALTER TABLE y ALTER DATABASE
•SELECT INTO
•GRANT y REVOKE

3
Reglas (Sintácticas).

- Creación de base de datos


CREATE DATABASE <nombre de base de datos>

- Eliminar una base de datos


DROP DATABASE <nombre de base de datos>

- Crear una tabla


CREATE TABLE <nombre de tabla> (<lista separada por comas de nombre atributo> <tipo de
atributo><especificaciones de validación opcionales> ) CONSTRAINT ( <nombre atributo > PK )
ON DELETE UPDATE CASCADE)
- Eliminar una tabla
DROP TABLE <nombre de la tabla>

- Modificar una estructura de una tabla:


- Agregar un atributo o columna a una tabla:
ALTER TABLE <nombre de la tabla> ADD COLUMN <nombre de campo><tipo de campo>

- Eliminar un atributo o columna a una tabla:


ALTER TABLE <nombre de la tabla> DROP COLUMN <nombre de campo>

- Modificar el tipo de atributo o columna de una tabla:


ALTER TABLE <nombre de la tabla> MODIFY COLUMN <nombre de campo><tipo de campo>

- Agregar registros a una tabla


INSERT INTO <nombre de la tabla> (<nombres de campos separados por comas> ) VALUES (
<valores separados por comas>)

Nota: Los campos de tipo auto numérico no se pueden incluir en la lista de nombres de los
campos que almacenarán los valores que se insertan. Cuando no existen campos de tipo auto
numérico en la estructura de la tabla, la lista de campos puede omitirse, pero el orden de los
valores deben listarse en el mismo orden que se usó para crear la tabla.

- Eliminar todos los registros de una tabla


DELETE FROM <nombre de tabla>

Nota: Cuando existen campos de tipo auto numérico, la tabla queda vacía y al insertarse nuevos
registros se toma como referencia para agregar nuevos registros el valor siguiente al último
valor que fue registrado antes de eliminar todos los registros.

Si se desea reiniciar la numeración de campos auto numéricos debe utilizarse la siguiente


instrucción:

4
TRUNCATE <nombre de tabla>

- Eliminar valores de registros de una tabla que cumplan con ciertas condiciones:
DELETE FROM <nombre de la tabla> WHERE <nombre campo><operador
condicional><nombre campo o valor>

- Modificar valores de registros de una tabla


UPDATE <nombre de tabla> SET <nombre campo> = <expresión> ú NULL> WHERE <condición
de búsqueda>

- Consulta de valores registrados en la tablas de datos:


SELECT <nombre de campos separados por comas> FROM <nombre de tablas separadas por
comas>

Nota: Cuando se incluyen todos los campos de las tablas pueden utilizarse el símbolo * en lugar
del nombre de campos.

En caso de que existan campos con el mismo nombre en distintas tablas referenciadas, debe
anteponerse al nombre del campo, el nombre o alias de la tabla correspondiente seguido de un
punto y el nombre del campo.

Los alias son cadenas que se utilizan para sustituir el nombre de la tabla en la consulta.

Clave primaria (Primary key).

La clave primaria se utiliza para identificar en forma única cada fila en la tabla. Puede ser parte
de un registro real, o puede ser un campo artificial (uno que no tiene nada que ver con el
registro real).

Una clave primaria puede consistir en uno o más campos en una tabla. Cuando se utilizan
múltiples campos como clave primaria, se los denomina claves compuestas.

Las claves primarias pueden especificarse cuando se crea la tabla (utilizando CREATE TABLE) o
cambiando la estructura existente de la tabla (utilizando ALTER TABLE).

Especificaciones de una clave primaria cuando se crea una tabla (Ejemplos):

En “MySQL”:
CREATE TABLE Customer
(SID integer,
Last_Name varchar(30),
First_Name varchar(30),
PRIMARY KEY (SID));

5
En “Oracle”:
CREATE TABLE Customer
(SID integer PRIMARY KEY,
Last_Name varchar(30),
First_Name varchar(30));

En “SQL Server”:
CREATE TABLE Customer
(SID integer PRIMARY KEY,
Last_Name varchar(30),
First_Name varchar(30));

Especificación de una clave primaria al modificar una tabla (Ejemplos):

En “MySQL”:
ALTER TABLE Customer ADD PRIMARY KEY (SID);

En “Oracle”:
ALTER TABLE Customer ADD PRIMARY KEY (SID);

En “SQL Server”:
ALTER TABLE Customer ADD PRIMARY KEY (SID);

Nota: Antes de utilizar el comando ALTER TABLE para agregar una clave primaria, necesitará
asegurarse de que el campo esté definido como 'NOT NULL' -- en otras palabras, NULL no puede
aceptarse como valor para ese campo.

Clave foránea (foreing key)

Una clave externa es un campo (o campos) que señala la clave primaria de otra tabla.

El propósito de la clave externa es asegurar la integridad referencial de los datos. En otras


palabras, sólo se permiten los valores que se esperan que aparezcan en la base de datos.

Por ejemplo, digamos que tenemos dos tablas, una tabla comprador que incluye todos los
datos del comprador, y la tabla órdenes que incluyen los pedidos del comprador.

La restricción aquí es que todos los pedidos deben asociarse con un comprador que ya se
encuentra en la tabla comprador.

En este caso, colocaremos una clave externa en la tabla órdenes y la relacionaremos con la
clave primaria de la tabla comprador.

6
De esta forma, nos aseguramos que todos los pedidos en la tabla órdenes estén relacionadas
con un comprador en la tabla comprador. En otras palabras, la tabla órdenes no puede contener
información de un comprador que no se encuentre en la tabla comprador.

La estructura de estas dos tablas será la siguiente:

Tabla Comprador

Nombre de columna Característica


Id Clave Primaria
Apellido
Nombre

Tabla Órdenes

Nombre de columna Característica


Id_orden Clave Primaria
Fecha_orden
Id_comprador Clave Externa
Monto

En el ejemplo anterior, la columna Id_comprador en la tabla Órdenes es una clave externa


señalando la columna Id en la tabla Comprador.

A continuación se muestran ejemplos de cómo especificar la clave externa a la hora de crear la


tabla Órdenes:

En “MySQL”:
CREATE TABLE ORDENES
(Id_orden integer,
Fecha_orden date,
Id_comprador integer,
Monto double,
Primary Key (Id_orden),
Foreign Key (Id_comprador) references COMPRADOR(Id));

En “Oracle”:
CREATE TABLE ORDENES
(Id_orden integer primary key,
Fecha_orden date,
Id_comprador integer references COMPRADOR(Id),
Monto double);

7
En “SQL Server”:
CREATE TABLE ORDENES
(Id_orden integer primary key,
Fecha_orden datetime,
Id_comprador integer references COMPRADOR(Id),
Monto double);

A continuación se presentan ejemplos para la especificación de una clave externa al modificar


una tabla: Esto asume que se ha creado la tabla ORDENES, y que la clave externa todavía no se
ha ingresado:

En “MySQL”:
ALTER TABLE ORDENES
ADD FOREIGN KEY (Id_comprador) REFERENCES COMPRADOR(Id);

En “Oracle”:
ALTER TABLE ORDENES
ADD (CONSTRAINT fk_orders1) FOREIGN KEY (Id_comprador) REFERENCES COMPRADOR (Id);

En “SQL Server”:
ALTER TABLE ORDENES
ADD FOREIGN KEY (Id_comprador) REFERENCES COMPRADOR(Id);

Restricciones (Check, Unique y Not Null).

La restricción CHECK se utiliza para limitar el rango de valores que puede ser colocado en una
columna.

1.- Si se define una restricción CHECK en una columna sólo permitirá ciertos valores de esa
columna.

2.- Si se define una restricción CHECK en una tabla puede limitar los valores de ciertas
columnas basándose en los valores de otras columnas en la fila.

Restricción CHECK de CREATE TABLE en SQL


Ejemplo la siguiente instrucción SQL crea una restricción CHECK en la columna "p_id" de la tabla
"Persons".

La restricción CHECK especifica que la columna "p_id" sólo debe incluir enteros mayores que 0.

8
En “MySQL”:

CREATE TABLE Persons


(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CHECK (P_Id>0)
)

En “SQL Server / Oracle / MS Access”:


CREATE TABLE Persons
(
P_Id int NOT NULL CHECK (P_Id>0),
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)

En múltiples columnas es de la siguiente manera:

En “MySQL / SQL Server / Oracle / MS Access”:


CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')
)

Restricción CHECK en ALTER TABLE en SQL

Para aplicar una restricción CHECK en la columna “P_Id” cuando la tabla ya está creada, usamos
la siguiente sentencia SQL:

En “MySQL / SQL Server / Oracle / MS Access”:


ALTER TABLE Persons
ADD CHECK (P_Id>0)

9
Restricción CHECK en DROP TABLE en SQL

Para utilizar la restricción CHECK en un drop, utilizamos:

En “SQL Server / Oracle / MS Access”:

ALTER TABLE Persons


DROP CONSTRAINT chk_Person

En “MySQL”
ALTER TABLE Persons
DROP CHECK chk_Person

Restricción (No Null)

En forma predeterminada, una columna puede ser NULL. Si no desea permitir un valor NULL en
una columna, querrá colocar una restricción en esta columna especificando que NULL no es
ahora un valor permitido.

Por ejemplo, en la siguiente instrucción,

CREATE TABLE Customer


(SID integer NOT NULL,
Last_Name varchar (30) NOT NULL,
First_Name varchar(30));

Las columnas “SID” y “Last_Name” no incluyen NULL, mientras que “First_Name” puede incluir
NULL.

Restricción (Unique)

La restricción UNIQUE asegura que todos los valores en una columna sean distintos.

Por ejemplo, en la siguiente instrucción,

CREATE TABLE Customer


(SID integer Unique,
Last_Name varchar (30),
First_Name varchar(30));

La columna “SID” no puede incluir valores duplicados, mientras dicha restricción no se aplica
para columnas “Last_Name” y “First_Name”.

10
Por favor note que una columna que se especifica como clave primaria también puede ser
única. Al mismo tiempo, una columna que es única puede o no ser clave primaria.

Valores predeterminados (default values)

Si al insertar registros no se especifica un valor para un campo que admite valores nulos, se
ingresa automáticamente "null" y si el campo está declarado "identity", se inserta el siguiente
de la secuencia. A estos valores se les denomina valores por defecto o predeterminados.

Un valor por defecto se inserta cuando no está presente al ingresar un registro y en algunos
casos en que el dato ingresado es inválido.

Para campos de cualquier tipo no declarados "not null", es decir, que admiten valores nulos, el
valor por defecto es "null". Para campos declarados "not null", no existe valor por defecto, a
menos que se declare explícitamente con la cláusula "default".

Para todos los tipos, excepto los declarados "identity", se pueden explicitar valores por defecto
con la cláusula "default".

Podemos establecer valores por defecto para los campos cuando creamos la tabla. Para ello
utilizamos "default" al definir el campo. Por ejemplo, queremos que el valor por defecto del
campo "autor" de la tabla "libros" sea "Desconocido" y el valor por defecto del campo
"cantidad" sea "0":

create table libros(


codigo int identity,
titulo varchar(40),
autor varchar(30) not null default 'Desconocido',
editorial varchar(20),
precio decimal(5,2),
cantidad tinyint default 0
);

Si al ingresar un nuevo registro omitimos los valores para el campo "autor" y "cantidad", Sql
Server insertará los valores por defecto; el siguiente valor de la secuencia en "codigo", en
"autor" colocará "Desconocido" y en cantidad "0".

Entonces, si al definir el campo explicitamos un valor mediante la cláusula "default", ése será el
valor por defecto.

También se puede utilizar "default" para dar el valor por defecto a los campos en sentencias
"INSERT", por ejemplo:

INSERT INTO libros (titulo,autor,precio,cantidad)


11
VALUES ('El gato con botas',default,default,100);
Si todos los campos de una tabla tienen valores predeterminados (ya sea por ser "identity",
permitir valores nulos o tener un valor por defecto), se puede ingresar un registro de la
siguiente manera:

INSERT INTO libros DEFAULT VALUES;

La sentencia anterior almacenará un registro con los valores predeterminados para cada uno de
sus campos.

Entonces, la cláusula "default" permite especificar el valor por defecto de un campo. Si no se


explicita, el valor por defecto es "null", siempre que el campo no haya sido declarado "not null".

Vistas (Views).

Las vistas pueden considerarse como tablas virtuales.

Generalmente hablando, una tabla tiene un conjunto de definiciones, y almacena datos


físicamente. Una vista también tiene un conjunto de definiciones, que se construye en la parte
superior de la(s) tabla(s) u otra(s) vista(s), y no almacena datos físicamente.

La sintaxis para la creación de una vista es la siguiente:

CREATE VIEW "NOMBRE_VISTA" AS "Instrucción SQL"

La “Instrucción SQL” puede ser cualquiera de las instrucciones SQL que hemos descripto en esta
guía de referencia.

Utilicemos un ejemplo simple para ilustrar. Supongamos que tenemos la siguiente tabla:

Tabla Customer
(First_Name char(50),
Last_Name char(50),
Address char(50),
City char(50),
Country char(25),
Birth_Date date)

y deseamos crear una vista denominada V_Customer que contiene sólo las columnas
First_Name, Last_Name y País de esta tabla, ingresaríamos

CREATE VIEW V_Customer


AS SELECT First_Name, Last_Name, Country
FROM Customer
12
Ahora tenemos una vista llamada V_Customer con la siguiente estructura:

View V_Customer
(First_Name char(50),
Last_Name char(50),
Country char(25))

Podemos utilizar también una vista para aplicar uniones a dos tablas. En este caso, los usuarios
sólo ven una vista en vez de dos tablas, y la instrucción SQL que los usuarios necesitan emitir se
vuelve mucho más simple. Digamos que tenemos las siguientes dos tablas:

Tabla Store_Information

store_name Sales Date


Los Angeles 1500 € 05-Jan-1999
San Diego 250 € 07-Jan-1999
Los Angeles 300 € 08-Jan-1999
Boston 700 € 08-Jan-1999

Tabla Geography

region_name store_name
East Boston
East New York
West Los Angeles
West San Diego

Y deseamos construir una vista que tenga ventas organizadas según la región. Colocaríamos la
siguiente instrucción SQL:

CREATE VIEW V_REGION_SALES


AS SELECT A1.region_name REGION, SUM(A2.Sales) SALES
FROM Geography A1, Store_Information A2
WHERE A1.store_name = A2.store_name
GROUP BY A1.region_name

Esto nos brinda una vista, V_REGION_SALES, que se ha definido para las ventas de los negocios
según los registros de la región. Si deseamos saber el contenido de esta vista, ingresamos,

SELECT * FROM V_REGION_SALES


13
Resultado:

REGION SALES
East 700 €
West 2050 €

Índices (indexes).

Los índices nos ayudan a obtener datos de las tablas en forma más rápida.

Utilicemos un ejemplo para ilustrar este punto: Digamos que estamos interesados en leer en un
libro de jardinería acerca de cómo cultivar pimientos.

En vez de leer el libro desde el comienzo hasta que encontremos una sección sobre pimientos,
es mucho más rápido para nosotros ir a la sección índice al final del libro, ubicar qué páginas
contienen la información sobre pimientos, y luego dirigirnos a esas páginas directamente.

Al dirigirnos al índice primero ahorramos tiempo y seguramente es el método más eficiente


para ubicar la información que necesitamos.

El mismo principio se aplica para la obtención de datos desde una tabla de base de datos. Sin
un índice, el sistema de base de datos lee a través de toda la tabla (este proceso se denomina
“escaneo de tabla”) para localizar la información deseada.

Con el índice correcto en su lugar, el sistema de base de datos puede entonces primero dirigirse
al índice para encontrar de dónde obtener los datos, y luego dirigirse a dichas ubicaciones para
obtener los datos necesarios. Esto es mucho más rápido.

Por lo tanto, generalmente se recomienda crear índices en tablas. Un índice puede cubrir una o
más columnas. La sintaxis general para la creación de un índice es:

CREATE INDEX "NOMBRE_ÍNDICE" ON "NOMBRE_TABLA" (NOMBRE_COLUMNA)

Digamos que tenemos la siguiente tabla:

Tabla Customer
(First_Name char(50),
Last_Name char(50),
Address char(50),
City char(50),
Country char(25),
Birth_Date date) 14
Si deseamos crear un índice tanto en Ciudad como en País, ingresaríamos,

CREATE INDEX IDX_CUSTOMER_LAST_NAME on CUSTOMER (Last_Name)

Para crear un indice en Customer colocamos:

CREATE INDEX IDX_CUSTOMER_LOCATION


on CUSTOMER (City, Country)

No hay una regla estricta respecto de cómo nombrar un índice. El método generalmente
aceptado es colocar un prefijo, tal como “IDX_”, antes del nombre de un índice para evitar la
confusión con otros objetos de la base de datos.

También es una buena idea brindar información sobre qué tabla y columna(s) se utilizará el
índice.

Por favor note que la sintaxis exacta para CREATE INDEX puede ser distinta según las diferentes
bases de datos. Debería consultar con su manual de referencia de base de datos para obtener
la sintaxis precisa.

15
Referencias (Bibliografía):

- Procedimientos almacenados y triggers -


1.- www.mssqltips.com/tutorial.asp?tutorial=161
2.- http://www.devjoker.com/contenidos/catss/278/Triggers-en-Transact-SQL.aspx
3.- http://es.scribd.com/doc/10325656/Procedimientos-Almacenados-y-Triggers-en-SQL-Server

- Clave primaria –
4.- http://www.1keydata.com/es/sql/sql-clave-primaria.php

- Clave foránea –
5.- http://www.1keydata.com/es/sql/sql-clave-externa.php

- Restricciones –
6.- http://www.w3schools.com/sql/sql_check.asp
7.- http://www.1keydata.com/es/sql/sql-constraint.php#check

- Valores predeterminados –
8.- http://www.sqlserverya.com.ar/temarios/descripcion.php?cod=27&punto=21

- Vistas –
9.- http://www.1keydata.com/es/sql/sql-create-view.php

- Índices –
10.- www.1keydata.com/es/sql/sql-create-index.php

16

S-ar putea să vă placă și