2012-05-24 26 views
7

En una base de datos SQLSQL: Insertar datos de otra tabla en una tabla que contiene las claves externas

Tengo una tabla Usuarios

Id Name Age AddressId 
----+------+------+----------- 

Dónde AddressID es una clave externa a unos nombres de tabla Direcciones

las direcciones de la tabla:

Id Country State City ZipCode 
----+---------+------+------+--------- 

Este es un uno-a-uno: cada usuario tiene la dirección y el 1 cada dirección tiene un usuario

tengo una nueva tabla newusers nombrados

Id Name 
----+------ 

Sólo tiene identificador y el nombre.

Lo que quiero hacer es esto:

escribir un script para insertar todos los registros de la tabla newusers en la tabla de usuarios.

  • Quiero que la edad para ser predeterminado 20 para todos los usuarios nuevos
  • Y para cada nuevo usuario inserta Necesito crear un nuevo registro de dirección para él
  • el nuevo registro de dirección tendrá todos lo que es valores (país, ciudad, estado, código postal) igual a "abcd" excepto el Id que se usará para establecer la clave externa ID de dirección para el nuevo usuario)

¿Cómo puedo hacer eso?

He intentado lo siguiente:

INSERT INTO Users(Name, Age) 
Values((SELECT Name FROM NewUsers),20) 

Pero no sé cómo crear un nuevo registro de direcciones para cada usuario insertar y especifique la clave externa en consecuencia.

Muchas gracias por cualquier ayuda

+0

es el 'Adresses.Id' y' IDENTITY'? –

+0

para crear una nueva dirección cuando inserta un nuevo 'Usuario' debe decidir crear' trigger' que se ejecutará después de insertar un nuevo Usuario. – Sajmon

+0

@ypercube sí, es Identity – Youssef

Respuesta

6

Un método sería con dos consultas, formada como la siguiente:

INSERT INTO Addresses (Country, State, City, ZipCode) 
SELECT 'abcd', 'abcd', 'abcd', 'abcd' FROM NewUsers 

INSERT INTO Users (Name, Age, AddressId) 
SELECT Name, 20, ?? FROM NewUsers 

Editar: Una forma sencilla de vincular los usuarios a las direcciones sería para configurar temporalmente el país al nombre de usuario. Entonces tendrías un enlace para determinar la ID de dirección. Una vez que la tabla de usuarios se rellena y se vincula de manera adecuada, se puede establecer país de nuevo en el valor predeterminado abcd:

insert addresses (country, state, city, zipcode) 
select name, 'abcd', 'abcd', 'abcd' from newusers; 

insert users (name, age, addressid) 
select u.name, 20, a.id from newusers u 
join addresses a on a.country = u.name; 

update a 
set a.country = 'abcd' 
from addresses a join newusers u on a.country = u.name; 

Demostración: http://www.sqlfiddle.com/#!3/1f09b/8

Hay formas más complejas de hacer esto si se quiere garantizar transaccional consistencia si pueden realizarse varias inserciones simultáneamente, o si desea permitir nombres duplicados, etc. Pero, según el ejemplo que ha proporcionado y los detalles hasta el momento, este método debería funcionar.

+0

Sí, se genera automáticamente – Youssef

0

Suponiendo que puede establecer AddressId como desee ...

INSERT Addresses 
(
    Id, 
    Country, 
    State, 
    City, 
    ZipCode 
) 
SELECT 
    Id, 
    'abcd', 
    'abcd', 
    'abcd', 
    'abcd' 
FROM NEWUsers 

INSERT Users 
(
    Id, 
    Name, 
    Age, 
    AddressId 
) 
SELECT 
    Id, 
    Name, 
    20, 
    Id 
FROM NEWUsers 

Si AddressId es una columna de identidad, primero puede deshabilitar la identidad temporalmente. Consulte SET IDENTITY_INSERT para obtener información y ejemplos.

2

Esto es un poco raro, pero hace lo que quiere en dos declaraciones: suponiendo que ningún usuario va a tener el nombre 'abcd' o ingrese eso para su país, y purga la tabla NewUsers después de esta operación:

INSERT dbo.Addresses(Country, State, City, ZipCode) 
OUTPUT inserted.Country, 20, inserted.id 
INTO dbo.Users 
SELECT Name, 'abcd', 'abcd', 'abcd' 
FROM dbo.NewUsers; 

UPDATE a SET Country = 'abcd' 
FROM dbo.Addresses AS a 
INNER JOIN dbo.NewUsers AS nu 
ON a.Country = nu.Name; 
+0

+1 Cool uso de la cláusula 'OUTPUT' :) – mellamokb

2

debe escribir Cursor para Insertar En Usuarios y tabla de direcciones con forign clave

DECLARE @AddressID INT, 
     @ID INT, 
     @Name NVARCHAR(50) 

DECLARE UserCursor CURSOR FOR 
SELECT ID, NAME 
FROM NewUsers 
OPEN UserCursor 

FETCH NEXT FROM UserCursor INTO @ID, @Name 
WHILE @@FETCH_STATUS =0 BEGIN 
    INSERT INTO Addresses(Country, State, City, ZipCode) 
    VALUES ('abcd', 'abcd', 'abcd', 'abcd') 

    SET @AddressID = SCOPE_IDENTITY() 

    INSERT INTO Users(Name, Age, AddressID) 
    VALUES (@Name, 20, @AddressID) 
    FETCH NEXT FROM UserCursor INTO @ID, @Name 
END 
CLOSE UserCursor 
DEALLOCATE UserCursor 
+0

" Must "es una palabra bastante fuerte. ¿Puede explicar por qué un cursor es la única opción? –

0

serio, la respuesta es que no quiere hacer lo que usted piensa que usted quiere hacer. Si los usuarios tienen una y solo una dirección, como indicó, entonces debe tener solo una tabla (usuarios) que contenga los campos de dirección. Modelar sus datos correctamente hará que este problema desaparezca intrínsecamente.

+0

Solo coloqué aquí un ejemplo solo para que las personas entiendan lo que necesito. de hecho, es mucho más complicado que esto y no tiene nada que ver con las direcciones y los usuarios – Youssef

Cuestiones relacionadas