2011-02-11 12 views
5

Me gustaría convertir una tabla existente en la 1ra forma normal (la normalización más simple posible; vea el ejemplo).¿Qué es el T-SQL para normalizar una tabla existente?

¿Por casualidad saber lo que es el T-SQL es para este tipo de problema? ¡Muchas gracias!

enter image description here

actualización

Probado por debajo de la respuesta, que funcionó a la perfección. Estos son los pasos que usé para probar la respuesta:

  1. Inicie Microsoft SQL Management Studio.
  2. Crea las tablas, con los datos a continuación.
  3. Asegúrese de que la ID en "Cliente" esté configurada en "Clave principal" e "Identidad".
  4. Asegúrese de que la ID en "Pedido" no tenga una configuración especial (es una clave externa).
  5. Abra un diagrama de base de datos, luego cree una relación 1: * entre las tablas "Cliente" y "Orden".
  6. Ejecute el script en la tabla "Cliente" y en la tabla "Orden", automáticamente normalizará los datos para usted.
  7. Esto es muy útil si usted está empezando desde un archivo .csv plana que acaba de ser importado, y que desea copiar la información en una forma normalizada en la base de datos.
+0

Su enlace de imagen no funciona. –

+0

Estoy de acuerdo en que esta es una refactorización sensata, pero no es normalización. No hay nada funcionalmente dependiente de 'name'. –

+0

Admito que este es un pequeño ejemplo de juguete para hacer la pregunta: el problema completo es un poco más complejo comparado con esto. – Contango

Respuesta

4

A partir de la tabla de clientes

INSERT INTO Customer (Name) 
SELECT DISTINCT Name 
FROM Flat_CSV_File 

Si ha repetido importaciones

INSERT INTO Customer (Name) 
SELECT DISTINCT f.Name 
FROM Flat_CSV_File f 
LEFT OUTER JOIN Customer c ON f.Name = c.Name 
WHERE c.Id IS NULL 

Ordenes (el nombre de su tabla Order es una palabra reservada en TSQL, por lo que debe citarla entre corchetes)

INSERT INTO [Order] (CustomerId, Description, Cost) 
SELECT c.Id, f.Description, f.Cost 
FROM Flat_CSV_File f 
INNER JOIN Customer c ON f.Name = c.Name 
+0

Perfecto, lo probé y funcionó a la perfección. – Contango

+1

Me pregunté por qué se usaban corchetes en [Orden], gracias por aclarar por qué. – Contango

0

Si se trata de un proceso único, manipularé primero el .csv y formaré sus tablas allí, incluidas las principales. Al rellenar la base de datos SQL, utilice

SET IDENTITY_INSERT Customers ON 

INSERT Customers 
(
    ... 
) 
SELECT 
    ... 
FROM 
    openrowset(...) 

SET IDENTITY_INSERT Customers ON 



SET IDENTITY_INSERT Orders ON 

INSERT Orders 
(
    ... 
) 
SELECT 
    ... 
FROM 
    openrowset(...) 

SET IDENTITY_INSERT Orders ON 

Si necesita una solución puramente TSQL, me gustaría crear tablas temporales para hacer la misma cosa básica, e insertar de las tablas temporales en lugar de la .csv.

+0

No hay ninguna razón para realizar un proceso en el que activar y desactivar la inserción de identidad. Esta no es una buena práctica. – HLGEM

4

La solución más sencilla es simplemente escribir una consulta para hacer la importación:

-- assuming that Id is an Identity column or has some default to generate keys. 
Insert Customer([Name]) 
Select Name 
From Flat_csv_file 
Group By Name 

Insert Order([Customer], [Description], Cost) 
Select C.Id, F.Description F.Cost 
From Customer As C 
    Join Flat_csv_file As F 
     On F.Name = C.Name 
+0

¡Agradable! Voy a intentar esto ahora. – Contango

4

En el caso anterior @Thomas tiene una solución perfectamente viable. Sin embargo, a veces las personas simplifican por hacer la pregunta, por lo que abordaré lo que podría querer hacer si necesita ir a muchas tablas (o la primera tabla no tiene una restricción única en el nombre, por ejemplo), no solo dos.

En primer lugar, voy a insertar los datos en una tabla de ensayo y añadir una columna para el id que será nulo. Luego, escribiría una inserción en la tabla primaria usando la cláusula OUTPUT para dar salida a los ID y la clave natural a una variable de tabla. Entonces usaría la variable de la tabla para actualizar el campo de identificación en la tabla de etapas.Luego insertaría registros de la tabla de etapas en otras tablas. Como ahora tengo la identificación allí, ya no es necesario acceder a la tabla principal original. (Si el número de registros es grande, también podría indexar la tabla de etapas).

Ahora, si no tiene una clave natural, el proceso se vuelve más difícil porque no tiene forma de identificar qué registro va a quién. Luego generalmente agrego una identidad a la tabla de etapas y luego realizo la importación inicial a la tabla padre un registro a la vez (incluyendo la tabla de etapas como una variable en el cursor) y luego actualizo la tabla de etapas con cada ID de tabla principal tal como está creado. Una vez que todos los registros iniciales se actualizan, utilizo procesos basados ​​en conjuntos para insertar o actualizar a las otras tablas.

La tabla de etapas también le ofrece la posibilidad de corregir localmente datos no válidos antes de intentar incluirlos en sus tablas de producción.

Otra sintaxis que puede necesitar saber si las cosas son complejas o si se trata de un proceso repetido es la sentencia MERGE. Esto insertará si se trata de un nuevo registro y actualización si se trata de un registro existente.

Si se trata de una transformación muy compleja, puede considerar el uso de SSIS.

+0

SSIS = SQL Server Integration Services – Contango

+0

Gracias por los comentarios, esto ayudará a crear un diseño de sistema robusto. – Contango

+0

Me preguntaba por qué no podía encontrar SSIS, sin importar dónde miraba. Eso es porque SSIS no es parte de Visual Studio 2010, tuve que instalar Visual Studio 2008 para encontrarlo. – Contango

Cuestiones relacionadas