Capitulo 3 – Lección 1: Tablas, tipos de datos e integridad de datos declarativa.

El concepto más básico de cualquier sistema de bases de datos relacionales(RDBMS) es la tabla. Sin embargo, las tablas han evolucionado significativamente desde las primeras versiones de RDBMS.
En este capítulo examinaremos las posibilidades y restricciones que existen cuando diseñamos las tablas, así como también incluiremos formas de optimizar sus estructuras de tablas y la integridad de datos.
Si no existiera la integridad de los datos declarativos, su base de datos puede terminar en una catástrofe de datos incorrectos.
Veamos un ejemplo para saber de que se trata la integridad declarativa: una vez un cliente se quejó de un pedido que él sabía que debería existir en la base de datos, y que decía que se había perdido. Mi primera impresión fue que probablemente se perdió a causa de un borrado accidental por parte del cliente, pero al consultar la base de datos, por supuesto, no existía el pedido. Así que ¿por qué no aparecía en la solicitud? Es simple: en la respectiva consulta que debía recuperar el pedido había un INNER JOIN a un cliente en la tabla con los clientes, el cual no existía! La tabla no tenía ninguna restricción de clave externa declarada entre el cliente y las tablas de pedido, y el cliente había sido borrados accidentalmente a pesar de que había pedidos existentes (y no entregados).

Lección 1: Trabajar con tablas y tipos de datos
El diseño, creación y mantenimiento de las tablas es una de las tareas más importantes de un desarrollador de bases de datos.
Tipos de datos
Antes de que pueda empezar a crear tablas, usted debe entender los diferentes tipos de datos que se pueden utilizar para definir los alcances de las columnas en las tablas, es decir, qué datos se pueden introducir en la columna. Hay dos tipos diferentes de tipos de datos en SQL Server:
  • Tipos de datos SQL Server
  • Tipos definidos por el usuario (UDT) de SQL o de Common Language Runtime (SQLCLR)
Ustedes deberían comienza por revisar los datos disponibles del sistema tipos y luego ver la posibilidad de simplificar el uso de tipos de datos mediante los UDT. UDT se implementan utilizando SQLCLR, que lo veremos mas adelante, en el capítulo 7.
Los datos disponibles del sistema tipos suelen dividirse en varios grupos,incluyendo numérico exacto, numérico aproximado, carácter,fecha y hora, y binarios.

Datos de tipo Caracter (Para mas info Clic AQUI):
Hay muy pocos tipos de datos de cadena distintos en SQL Server, char, varchar, nchar, nvarchar, text y ntext. Los tipos de text y ntext son obsoletos, por lo que hay que evitar su uso. Ellos han sido sustituidos por varchar(max) y nvarchar(max). Todos los tipos char tomar un parámetro, que es el número de caracteres para soportar el almacenamiento. La diferencia entre char y varchar (así como entre nchar y nvarchar)es que char es de longitud fija y varchar es de longitud variable. Esto significa que los char siempre asignan un espacio de almacenamiento suficiente para almacenar toda su longitud y varchar almacena sólo los datos reales introducidos. La ventaja de usar char sobre varchar es que las actualizaciones realizadas a una columna CHAR no requieren mover la fila porque los datos que se introducen siempre, ya que caben en el espacio asignado. Tenga en cuenta que esta ventaja es casi siempre superado por el hecho de que varchar utiliza mucho menos espacio de almacenamiento que char (considerar varchar(100) vs char(100) ].
Con char y varchar, una collation se utiliza para especificar la página de códigos(conjunto de caracteres) a utilizar para almacenar e interpretar el contenido de las columnas. La collation también se utiliza para decidir cómo ordenar y comparar los datos almacenados en estas columnas. Hay 2.397 variaciones de collation disponibles en SQL Server 2008, tres de los cuales son Japanese_CI_AI,Finnish_Swedish_CI_AI y Latin1_General_CI_AI. El resto se puede encontrar consultando la tabla con valores de función fn_helpcollations.
La collation Japanese_CI_AI usa la página de códigos 932 para soportar el almacenamiento de caracteres japoneses. Y  las collation Finnish_Swedish_CI_AI y Latin1_General_CI_AI utilizan la página de códigos 1252. La parte del nombre de _CI_AI de la collation especifica si la intercalación no distingue entre mayúsculas y minúsculas (case-insensitive = CI) o si distingue mayúsculas y minúsculas (case-sensitive = CS), así como que sea insensible a los acentos (accent-insensitive = AI) o sensible a los acento (accent-sensitive = AS). Es importante saber que lo que se considera un "acento" es diferente en diferentes idiomas y, por tanto, en distintas intercalaciones también.Tome el carácter ö , por ejemplo. En Latin1_General_CI_AI, ö se considera un acento o, lo que significa que 'o' = 'ö' devolverá true; por otro lado, en Finnish_Swedish_CI_AI, ö se considera un carácter independiente y 'o' = 'ö' devolverá False.
Por último, ¿qué pasa con nchar y nvarchar? Estos dos personajes tipos de datos de almacenamiento utilizan la página de código Unicode universal (UCS-2). Esto significa que si usted utiliza nchar o nvarchar, puede almacenar cualquier tipo de caracteres, independientemente de la intercalación que usted elija, ya que dos bytes siempre se utilizan para almacenar cada caracter. Comparemos esto con varchar y char, que almacenan los caracteres usando uno o dos bytes en función de la colación. Recuerde que usted todavía necesita especificar la collation porque la collation aún decide la manera de ordenar y comparar los datos almacenados en su columna.
Si desea utilizar una collation diferente a la especificada en una columna al hacer una comparación, se puede especificar en una expresión. Aquí está un ejemplo que muestra la cláusula WHERE especifica una collation:
WHERE Name = 'Öqvist' COLLATE Finnish_Swedish_CI_AS

Tenga en cuenta que al cambiar la collation en la expresión, SQL Server no puede utilizar un índice definido en la columna para realizar una operación de búsqueda debido a que el índice se ordena de acuerdo con otro cotejo.

Datos de tipo Numérico exacto (Para mas info Clic AQUI y AQUI)::
Los tipos numéricos exactos se componen de un tipo fijo de número entero (o parte entero)  y una parte de punto decimal. Todos los tipos numéricos exactos siempre produce el mismo resultado, independientemente de qué tipo de arquitectura del procesador está siendo utilizada o la magnitud de los números (es decir, qué tan grande que los números son). Tabla 3-1 enumera los tipos disponibles de datos numérico exacto.


Tipo de Dato

Tamaño de Almacenamiento

Posibles Valores

Comentarios

tinyint

1 byte

0 a 255

Igual al tipo de datos byte en lenguajes de programación, no puede almacenar los valores negativos

smallint

2 bytes

–32768 a 32767

Un entero de 16 bits con signo

int

4 bytes

–2,147,483,648 a
2,147,483,647

Un entero de 32 bits con signo

bigint

8 bytes

–2E63 a 2E63 –1

Un entero de 64 bits con signo

decimal
(precision,
scale)

5 a17 bytes
dependiendo de la precision

–10E38 +1 a
10E38 –1

Un número decimal que contienen hasta 38 dígitos

numeric
(precision, scale)

funcionalmente equivalente al tipo de dato numeric

funcionalmente equivalente al tipo de dato numeric

funcionalmente equivalente al tipo de dato numeric

Mientras que los tipos de datos enteros (tinyint, smallint, int y bigint) no aceptan ningún parámetro, los tipos de datos decimal (y numérico) si lo hacen. Cuando se utiliza el tipo de datos decimal, se puede especificar la precisión y la escala de valores almacenados según el tipo de datos. La precisión define el número total de dígitos que el tipo de datos puede tener, llegando una precisión máxima de 38, y la escala define la cantidad de los dígitos definidos por la precisión que se usan como decimales.
Un decimal definido como decimal (38,0) permite sólo números enteros y un decimal definido como decimal (38, 38) permite sólo los decimales. Si se define una columna solo como decimal, sin especificar la precisión y la escala, se hace la precisión predeterminada de 18 y la escala de 0. Dependiendo de la precisión que se especifica el tipo de datos decimal, lo que requiere entre 5 y 17 bytes de almacenamiento. Es importante que usted elija el valor más bajo de precisión apropiado, para conservar espacio de almacenamiento, así como los recursos de memoria. En la siguiente tabla, se muestra el almacenamiento requerido por las diferentes precisiones. Tenga en cuenta que la escala seleccionada no tiene ningún efecto sobre los requisitos de almacenamiento.
Precisióntamaño
1 a 9
5 bytes
10 a 19
9 bytes
20 a 28
13 bytes
29 a 3817 bytes

Datos de tipo Numérico aproximado (Para mas info Clic AQUI):
SQL Server admite dos tipos de datos, de coma flotante o valor aproximado numérico (float y real). Al igual que el tipo de datos decimal descrito previamente, el tipo de datos float acepta un parámetro. El parámetro suministrado al tipo de datos float define el número de bits que se utilizan para almacenar la mantisa del número de punto flotante. Cualquier valor del parámetro inferior o igual a 24 se interpreta como 24, y algo por encima de 24 se interpreta como 53. Esto significa que la mantisa es de 24 o 53 bits de, según el valor que usted proporciona a los parámetros del campo float.
Tipos de datos numéricos y aproximados que se utilizan con datos numéricos de coma flotante. Los datos de coma flotante son aproximados; por tanto, no todos los valores del intervalo del tipo de datos se pueden representar con exactitud.
Tipo de datoTamaño almacenamientoPosibles Valores

float (n <= 24)
4 bytes–3.40E38 a –1.18E-38, 0 y 1.18E-38 a 3.40E38

float (24 > n <= 53)
8 bytes–1.79E308 a –2.23E-308, 0 y 2.23E-308 a 1.79E308
realFuncionalmente equivalente a float(24)Funcionalmente equivalente a float(24)

Datos de tipo Fecha y Hora (Para mas info Clic AQUI):

SQL Server admite los tipos de fecha y hora siguientes:

Tipo de datos

Intervalo

Precisión

Tamaño de almacenamiento (bytes)

time

De 00:00:00.0000000 a 23:59:59.9999999

100 nanosegundos

De 3 a 5

date

De 0001-01-01 a 9999-12-31

1 día

3

smalldatetime

De 1900-01-01 a 2079-06-06

1 minuto

4

datetime

De 1753-01-01 a 9999-12-31

0,00333 segundos

8

datetime2

De 0001-01-01 00:00:00.0000000 a 9999-12-31 23:59:59.9999999

100 nanosegundos

De 6 a 8

datetimeoffset

De 0001-01-01 00:00:00.0000000 a 9999-12-31 23:59:59.9999999 (en UTC)

100 nanosegundos

De 8 a 10

Una de las características más esperadas de SQL Server 2008 ha sido la introducción de los nuevos tipos de datos de fecha y hora. Antes de SQL Server 2008, el programa tenía dos tipos de datos para la gestión de fecha y hora: datetime y smalldatetime. Dado que ambos tipos de datos están todavía en uso en SQL Server 2008 hoy, y que tomará mucho tiempo antes de todas las bases de datos actualizadas a SQL Server 2008 se conviertan en los nuevos tipos de datos de fecha y hora, es muy importante para entender cómo utilizar los tipos de datos smalldatetime y datetime. Hay dos grandes problemas con el tipo de datos de fecha y hora. El primer problema es que la fecha y la hora se almacenan juntos, cosa que no siempre es deseable. Tome la siguiente consulta, en la que desea recuperar todos los pedidos realizados el 18 de agosto de 2008:
SELECT SalesOrderID,CustomerId,OrderDate
FROM Sales.SalesOrderHeader
WHERE OrderDate = '20080818';

Esta consulta devuelve sólo los pedidos realizados el 18 de agosto de 2008,exactamente a las 00:00:00. Para resolver este problema, debe controlar la porción de tiempo del tipo de datos de fecha y hora correcta en la consulta. Hacer esto nos lleva al segundo problema con el tipo de datos de fecha y hora, que es la precisión de la porción de tiempo del tipo de datos. La unidad más pequeña de tiempo que se admite es uno de cada tres milisegundos (por smalldatetime, es cada minuto).Esto significa que el último dígito de una instancia de fecha y hora (es decir, yyyy-MM-dd hh: mm: ss.xxx) sólo puede ser 0, 4, o 7. Esto a su vez significa que el ultimo valor soportada de fecha y hora del día es 23:59:59.997. El tiempo de23:59:59.998 redondea hacia abajo al 23:59:59.997, y el tiempo de 23:59:59:999rondas hasta el día siguiente a las 00:00:00.000. Este comportamiento es muy importante tener en cuenta cuando se trabaja con el tipo de datos de fecha y hora.Continuando con el ejemplo de la consulta de la tabla Sales.SalesOrderHeader para todos los pedidos del 18 de agosto de 2008, usted tiene que utilizar una de las siguientes dos consultas para obtener el resultado deseado:
-- Consulta #1
SELECT SalesOrderID,CustomerId,OrderDate
FROM Sales.SalesOrderHeader
WHERE OrderDate BETWEEN '2008-08-18T00:00:00' 
AND '2008-08-18T23:59:59.997';

-- Consulta #2SELECT SalesOrderID, CustomerId,OrderDate
FROM Sales.SalesOrderHeader
WHERE OrderDate >= '20080818' 
AND OrderDate < '20080819';

A pesar de que las dos consultas producen el mismo resultado, se debe considerar el uso de la segunda consulta, ya que también maneja correctamente el nuevo tipo de datos datetime2. Esto es porque el tipo de datos datetime2 puede almacenar fracciones de tiempo de inactividad de 100 nanosegundos (o 0,0000001 de segundo), lo que significa que 0.997 no es la última milésima de segundo del día.Cada vez que consulta los datos de tiempo, usted debe tratar de utilizar un predicado "menor que" para evitar depender de una precisión segunda fracción específica. Finalmente, al convertir una cadena literal a un tipo de datos datetime o smalldatetime, siempre debe utilizar el formato AAAAMMDD fechas sin tiempo, y el formato AAAA-MM-DDTHH: MI: SS.XXX para fechas con segundos. Ambos formatos de trabajo son independiente del lenguaje y los formatos de fecha vigente en su conexión.

Describamos los nuevos tipos de datos de SQL server 2008 (datetime2, date, time, and datetimeoffset.):
  • Date: es un tipo de datos que puede almacenar sólo fechas. Debido a este hecho, este tipo de datos es perfecto para su uso en todos los casos en que no se requiere horas. Esto simplifica las consultas porque la cuestión del tiempo descrito anteriormente, no existe y porque este tipo de datos ahorra espacio de almacenamiento mediante la asignación de sólo 3 bytes. Al convertir una cadena literal al tipo de datos de fecha, siempre se debe utilizar el formato AAAA-MM-DD(siempre incluyendo el siglo).
  • Time: es un tipo de datos que puede almacenar horas sin una fecha. Para este tipo de datos, puede proporcionar un parámetro opcional que especifica la precisión o número de decimales de una fracción de segundos que desea que la instancia soporte. Los valores posibles que puede proporcionar son entre 0 y 7, es decir, entre el segundo que es el valor más bajo (0) y 100 nanosegundos que es el valor más pequeño (7). Si no se especifica este parámetro cuando se declara el tipo de datos, se utiliza el valor 7. Al convertir una cadena literal al tipo de datos en tiempo, siempre se debe usar el formato HH:MI:SS.NNNNNNN. El tamaño de almacenamiento utilizado por el tipo de datos de tiempo depende de la precisión especificada. El espacio de almacenamiento utilizado en función de la precisión especificada, siendo de 3 bytes para una precisión de 0 a 2, de 4 bytes para una precisión de 3 a 4 y de 5 bytes para una precisión de 5 a 7.
  • datetime2: El tipo de datos datetime2 es una combinación de los tipos de datos de fecha y hora, con el parámetro de la misma precisión de fracciones de segundo que el tipo de datos time. Al convertir una cadena literal al tipo de datos datetime2, siempre debe utilizar el formato YYYY-MM-DD HH:MI:SS.NNNNNNN. El espacio de almacenamiento utilizado por el tipo de datos datetime2 en función de la precisión especificada es la siguiente: 6 bytes para una precisión de 0 a 2, de 7 bytes para una precisión de 4 a 5 y de 8 bytes para una precisión de 6 a 7.
  • datetimeoffset: Además de lo que es el tipo datetime2, este nuevo formato almacena un desplazamiento de zona horaria. Esto puede ser muy útil cuando es importante conocer no sólo el momento en que algo sucedió, pero también en qué zona hora en que ocurrió. Al convertir una cadena literal al tipo de datos datetimeoffset, siempre debe utilizar el formato DD HH:MI:SS.NNNNNNN +|-HH:MI. El espacio de almacenamiento utilizado en función de la precisión especificada es la siguiente: 6 bytes para una precisión de 0 a 2, de 7 bytes para una precisión de 4 a 5 y de 8 bytes para una precisión de 6 a 7.
Fundamentos básicos de las tablas
La tabla es el objeto central de la mayoría de los RDBMS. En SQL Server, hay muchas variantes de tablas: tablas permanentes (las tablas comunes), las tablas temporales locales, tablas temporales globales, y las tablas variables.

Creando una tabla:
Antes de que usted puede crear una tabla, es necesario un esquema en el que se creara la tabla. Un esquema es similar a un espacio de nombres en muchos otros lenguajes de programación,. Sin embargo, sólo puede haber un nivel de esquemas (es decir, los esquemas no pueden residir en otros esquemas). Ya hay varios esquemas que existen en una base de datos de nueva creación: el dbo, sys y information_schema. El esquema dbo es el esquema predeterminado para los nuevos objetos, mientras que sys y information_schema schemas son utilizados por los diferentes objetos del sistema. Antes de SQL Server 2005, los esquemas no existían.
En vez del objeto que residían en un esquema, el objeto pertenecía a un usuario de base (sin embargo, la sintaxis es la misma:. <owner> <object>) En estas versiones,dbo se recomienda propietaria de todos los objetos, pero esto ya no se utiliza mas. A partir de SQL Server 2005, todos los objetos deben ser creados dentro de un esquema definido por el usuario. Los esquemas son creados con la instrucción CREATE SCHEMA, como se muestra en el siguiente ejemplo de la creación de un esquema y una mesa dentro de ese esquema:
CREATE SCHEMA Sales;
GO
CREATE TABLE Sales.Customers (
CustomerId INT NOT NULL
,Name NVARCHAR(50) NOT NULL );

Se crean las tablas, ya sea usando la sentencia CREATE o SELECT. . . INTO (el SELECT... INTO crea una nueva tabla sobre la base de una consulta). La sintaxis básica de la instrucción CREATE TABLE se muestra aquí:

CREATE TABLE
    [ database_name . [ schema_name ] . | schema_name . ] table_name
      ( { <column_definition> | <computed_column_definition>
          | <column_set_definition> }
          [ <table_constraint> ] [ ,...n ] )
               [ ON { partition_scheme_name ( partition_column_name ) | filegroup
                | "default" } ]
       [ { TEXTIMAGE_ON { filegroup | "default" } ]
     [ WITH ( <table_option> [ ,...n ] ) ]
[ ; ]


Antes de entrar en los detalles de la sintaxis, vamos a ver las reglas que se aplican al nombrar tablas y columnas.

Nombres de tabla y columna (identificadores)Ambos tabla y de columna son los identificadores, y deben atenerse a ciertas reglas.
Los identificadores son estándar o delimitado. Los requisitos de cada uno de estos se describen a continuación.
Identificadores estándar:
  • El primer carácter debe ser una letra o un guión bajo (_), no un dígito.
  • El primer carácter puede ser también un signo de arroba (@) o un signo de número(#), pero ambos tienen un significado especial
    • @ define una variable o parámetro.
    • @@ No significa otra cosa que @, y no debe ser utilizado debido a que muchos de las funciones del sistema comienzan con @@.
    • # Define un objeto temporal (es decir, el objeto sólo está disponible a partir de la conexión actual).
    • ## Define un objeto temporal global (es decir, el objeto está disponible desde cualquier conexión en la misma instancia).
  • Los siguientes caracteres pueden incluir letras, dígitos, el signo de arroba (@), el signo de dólar ($), el signo de número (#), y el guión bajo (_).
  • El identificador no debe ser una palabra reservada de T-SQL.
  • Espacios o caracteres especiales incrustados no están permitidos.
Identificadores delimitados:
Cualquier identificador que no se adhiere a las reglas de nomenclatura estándar de identificación debe ser delimitado ya sea mediante comillas (") o corchetes ([]). Uso de las comillas se ajusta al estándar ANSI SQL, sin embargo, debe ser consciente de que la configuración de sesión SET QUOTED_IDENTIFIER debe establecerse en ON para las comillas se puedan utilizar para los identificadores delimitados. (Los corchetes se puede utilizar siempre para los identificadores delimitados.) La configuración predeterminada para QUOTED_IDENTIFIER se establece en ON, pero los viejos códigos de T-SQL pueden requerir que se establezca en OFF. Establecer QUOTED_IDENTIFIER en OFF, para que SQL Server interprete las comillas como cadenas en vez de como identificadores. Ejemplos:
-- identificador estándar
CREATE TABLE HR.Employees (
EmployeeId INT NOT NULL );

-- Identificador con delimitadores:
SET QUOTED_IDENTIFIER ON;
CREATE TABLE HR."Organisation Employees" (
"Employee Id" INT NOT NULL );
-- o
CREATE TABLE HR.[Organisation Employees] (
[Employee Id] INT NOT NULL );


Creando la tabla!
Ahora, echemos un vistazo a la creación de una tabla sencilla. Considere este ejemplo:

CREATE TABLE HR.Employees (
EmployeeId INT NOT NULL
,FirstName NVARCHAR(50) NOT NULL
,LastName NVARCHAR(50) NOT NULL
,PhoneNumber VARCHAR(15) NULL
,BirthDate DATE NOT NULL);

Este código crea una tabla llamada Employees con cinco columnas. La sentencia CREATE TABLE empieza por definir el esquema donde la tabla debe residir (en este caso, de recursos humanos), nombre de la tabla (Employees) y las columnas de la tabla. Las columnas se definen mediante tres propiedades básicas:nombre de la columna, el tipo de datos, y la aceptación de valores NULL (si la columna admite valores NULL).


Instrucciones de nomenclatura:
Al elegir el nombre de tablas y columnas, es importante seguir las directrices de denominación de proyecto. A algunas pautas típicas de denominación se ofrecen a continuación:
  • Use PascalCasing (también conocida como upper camel casing).
  • Evite las abreviaturas.
  • Un nombre largo que los usuarios entiendan es preferible a un nombre corto que los usuarios no entiendan.
Seleccionando Tipos de Datos:
El tipo de datos para cada columna es también muy importante. Ya hemos cubierto la mayoría de los tipos de datos disponibles en SQL Server 2008, pero esta sección se describen algunas pautas que usted debe tratar de seguir a la hora de decidir qué tipo de datos a utilizar. Son los siguientes:

  • Utilice siempre el tipo de datos que requiere la menor cantidad de espacio en disco sin dejar de ofrecer la funcionalidad que usted requiere.

  • Puede ser muy costoso (en tiempo de desarrollo y recursos de los servidores)cambiar el tipo de una columna de datos más adelante. No utilice un tipo de datos si hay una posibilidad de que no va a cubrir las necesidades futuras de la aplicación.
  • En la mayoría de los casos utilizar un tipo de datos de longitud variable, como nvarchar, en lugar de un tipo de datos de longitud fija, como nchar.
  • Uno de los pocos casos en que se prefiere un tipo de datos de longitud fija a un tipo de datos de longitud variable es si los cambios en la columna van a suceder con mucha frecuencia. Si el valor de la columna se actualiza con frecuencia, el costo del traslado de la fila a una nueva posición con el nuevo valor puede ser mayor que el costo del almacenamiento adicional requerida por un tipo de dato fijos.
  • Evite el uso de la datetime y smalldatetime debido a que utilizan más espacio en disco y ofrecer menor precisión que el nueva formato date, time y datetime2.
  • Utilice el varchar(max), nvarchar(max) y varbinary(max) en lugar de text, ntext, y tipos de datos image, que pueden no estar disponibles en futuras versiones de SQL Server.
  • Utilice el tipo de datos rowversion en lugar del tipo de datos timestamp debido a que el tipo de datos timestamp puede no estar disponible en futuras versiones de SQL Server.
  • Sólo utilice el varchar(max), nvarchar(max), varbinary(max), y los tipos de datos xml, si un tipo de datos con un tamaño especificado no se puede utilizar. Esto es porque el uso de los tipos de datos le impide ser capaz de reconstruir los índices en línea y porque estos tipos de datos no se pueden utilizar en la clave de un índice.
  • Use el tipo de datos float o real sólo si la precisión proporcionada por decimal es insuficiente.
NULL o NOT NULL?
La decisión sobre si se debe permitir valores nulos en una columna puede ser un problema. Mucha gente tiene opiniones muy fuertes sobre valores NULL, o bien  aceptados o que están fuertemente en contra de ellos. La decisión de permitir valores nulos es realmente fácil de hacer: En general, nunca los permita porque es la forma más sencilla de diseñar la tabla. Permitir valores nulos en donde no es necesario hacerlo aumenta el potencial de problemas cuando se consultan las tablas.
Si el valor de la columna es opcional (es decir, no todos los registros tienen un valor), la columna debe permitir valores NULL. Nunca se debe utilizar otro valor en lugar de NULL (como -1 para los números enteros), lo que podría causar muchos problemas en sus consultas. Esto se debe a -1 significa "menos uno" y no "desconocido", que es la definición de NULL. Por ejemplo, si se utiliza la función AVG, que incluye valores -1 en el cálculo, pero AVG se omite el valor NULL. Por otra parte, añadir una nueva tabla con una relación uno a uno en la tabla que está diseñando y almacenar el valor potencial desconocida en la otra tabla. Si una fila no debe tener un valor, simplemente no se inserta una fila en la otra tabla.Considere este ejemplo:

CREATE TABLE HR.Employees (
EmployeeId INT NOT NULL
,FirstName NVARCHAR(50) NOT NULL
,LastName NVARCHAR(50) NOT NULL
,BirthDate DATE NOT NULL );
CREATE TABLE HR.EmployeePhoneNumbers (
EmployeeId INT NOT NULL
,PhoneNumber VARCHAR(15) NOT NULL);
-- Empleado con numero de teléfono:
INSERT HR.Employees (EmployeeId, FirstName, LastName, BirthDate)
VALUES (1, N'John', N'Kane', '1970-02-20');
INSERT HR.EmployeePhoneNumbers (EmployeeId, PhoneNumber)
VALUES (1, N'+1-425-555-1234');
-- Empleado sin numero de teléfono:INSERT HR.Employees (EmployeeId, FirstName, LastName, BirthDate)
VALUES (2, N'Jane', N'Dow', '1965-05-30');

Esta implementación no es muy usada debido a que aumenta la necesidad de consultas con combinaciones OUTER o subconsultas para recuperar la columna "nullable"de la tabla. Esto, a su vez, aumenta el riesgo de problemas de rendimiento y también añade más complejidad a las preguntas que sólo permite valores NULL en la tabla original.

Identity


Todas las tablas deben tener una columna o una combinación de columnas que identifica de forma única las filas de la tabla. Esto se conoce como la clave principal.La mayoría de las veces, es difícil seleccionar una columna de datos cuyos valores hacen una buena clave principal, por lo general, porque los valores no se garantiza que sea único o porque los valores pueden cambiar con frecuencia. En lugar de utilizar una columna, llamada una clave natural, puede utilizar una técnica o de claves generadas automáticamente.
la propiedad IDENTITY se utiliza para designar una columna por tabla cuyo valor debe ser aumentado o disminuido de forma automática cuando se agregan nuevas filas. La sintaxis para crear una columna de identidad es <column name> <data type> IDENTITY(<seed>, <increment>) NOT NULL.
La seed es el punto de partida para la generación de números, y el incremento es el valor por el cual se incrementa la tecla (o disminuye, si es negativo). Una columna de identidad no puede permitir valores NULL. El ejemplo siguiente crea la tabla hr.employees y define la columna de employees con una identidad que se inicia en1000 y se incrementa en un valor de 2 para cada fila:

CREATE TABLE HR.Employees (
EmployeeId INT IDENTITY(1000, 2) NOT NULL
,FirstName NVARCHAR(50) NOT NULL
,LastName NVARCHAR(50) NOT NULL
,BirthDate DATE NOT NULL);


Tenga en cuenta que la propiedad IDENTITY sólo se puede especificar la hora de crear una nueva columna. Una columna existente no puede ser modificado para utilizar la propiedad IDENTITY. Para cambiar una columna existente, la columna existente debe ser eliminado y la columna de identidad añadido o creada en su lugar.
La columna de identidad se puede utilizar sólo en los tipos de datos que almacenan números enteros, que incluyen tanto los tipos de datos integer y el tipo de datos decimal con una escala establecida en 0.
Otro punto importante a señalar con columnas de identidad es que no están garantizados para generar secuencias completas. Si una inserción falla, todavía utiliza el valor de identidad, creando un agujero en la secuencia. Considere este ejemplo:

INSERT HR.Employees (FirstName, LastName, BirthDate)
VALUES ('John', 'Kane', '1970-01-30');
-- EmployeeID generated: 1000
GO
INSERT HR.Employees (FirstName, LastName, BirthDate)
VALUES ('John', 'Kane', '1970-01-32');
-- Falla porque la fecha es invalida
GO
INSERT HR.Employees (FirstName, LastName, BirthDate)
VALUES ('Jane', 'Dow', '1972-03-30');
-- EmployeeID


En este ejemplo, la segunda instrucción INSERT falla y la clave de 1002 se omite, por lo que Jane Dow se inserta con la clave 1004.

Compresión:
SQL Server 2008 introduce la posibilidad de comprimir los datos en las tablas e índices, si se utiliza SQL Server 2008 Enterprise Edition. La compresión de datos se lleva a cabo en dos niveles: de fila y página. La declaración siguiente se configura una tabla para uso a nivel de compresión de página:

ALTER TABLE HR.Employees
REBUILD
WITH (DATA_COMPRESSION = PAGE);

Si activa la compresión a nivel de fila, SQL Server cambia el formato utilizado para almacenar filas.
En términos simples, este formato de registro convierte todos los tipos de datos de tipos de datos de longitud variable. También ningún espacio se utiliza  para almacenar los valores NULL. Los tipos de datos de longitud fija (por ejemplo, datetime2, int, decimal, y nchar) que se utilizan en una tabla, es más probable que se beneficien de la compresión a nivel de fila.
A nivel de página incluye la compresión a nivel de fila de compresión y se agrega a nivel de página de compresión usando Diccionario Page,y el prefijo de la columna. Diccionario Page, simplemente introduce punteros entre las filas de la misma página para evitar el almacenamiento de datos redundantes. Considere la siguiente página simplificada almacenar los nombres de:

Row 01: John Kane
Row 02: John Woods
Row 03: John Kane
Si esta página utiliza Diccionario Page, se vería así

Row 01: John Kane
Row 02: John Woods
Row 03: 01

En este caso, el valor en la fila 03 puntos para el valor en la fila 01, el ahorro de varios bytes de almacenamiento.
La compresión de página también incluye un prefijo de columna, que es similar al diccionario de página, pero puede volver a utilizar partes de los valores.
Al considerar la posibilidad de utilizar de fila o página a nivel de compresión, que es muy importante para verificar la cantidad de espacio que ahorra realmente mediante la activación de la compresión.


Resumen de la lección:
  • Creación de tablas es algo más que la definición de las columnas. Es muy importante elegir el tipo de datos correcto e implementar integridad de datos.
  • Usted necesita saber los detalles de cómo los diferentes tipos de datos se comportan antes de poder usarlos correctamente.
  • Necesidades de integridad de datos que una parte de su definición de la tabla desde el principio para asegurarse de que proteger sus datos contra fallos.

No hay comentarios:

Publicar un comentario