2012-05-24 12 views
7

w bazie danych SQLSQL: Wstaw dane z innej tabeli w tabeli, która zawiera klucze obce

Mam tabeli użytkowników

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

Gdzie AddressId jest kluczem obcym do nazw tabel Adresy

Tabela Adresy:

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

to jest jeden-do-jednego związku: każdy użytkownik ma 1 adres i każdy adres ma jeden użytkownik

Mam nową tabelę o nazwie newusers

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

Ma tylko identyfikator i nazwę.

co chcę zrobić to:

napisać skrypt, aby wstawić wszystkie rekordy z tabeli newusers w tabeli użytkowników.

  • Chcę Wiek być domyślna 20 dla wszystkich nowych użytkowników
  • I dla każdego nowego użytkownika włożona trzeba utworzyć nowy rekord Adres dla niego
  • nowy rekord Adres będzie miał wszystkich jego wartości (kraj, miasto, stan, kod pocztowy) równym "abcd" z wyjątkiem identyfikatora, który będzie używany do ustawiania klucza obcego AddressId dla nowego użytkownika)

Jak mogę to zrobić?

Próbowałem następujące:

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

Ale nie wiem, jak utworzyć nowy rekord Adres dla każdego użytkownika włożonej i określić klucz obcy odpowiednio.

dziękuję za wszelką pomoc

+0

jest "Adresses.Id' an" TOŻSAMOŚĆ "? –

+0

aby utworzyć nowy adres po wstawieniu nowego 'User', powinieneś zdecydować się na" wyzwalacz ", który zostanie wykonany po wstawieniu nowego użytkownika. – Sajmon

+0

@ypercube tak to jest Identity – Youssef

Odpowiedz

6

Jednym ze sposobów byłoby z dwoma zapytaniami, uformowana jak następuje:

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 

Edit: Jeden prosty sposób połączyć użytkownikom adresów byłoby tymczasowo ustawić kraj na nazwę użytkownika. Następnie masz link do określenia adresu. Gdy tabela użytkowników jest wypełniana i związał się prawidłowo, można ustawić kraj z powrotem do wartości domyślnej 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; 

Demo: http://www.sqlfiddle.com/#!3/1f09b/8

Są bardziej skomplikowane sposoby, aby to zrobić, jeśli chcesz, aby zagwarantować transakcyjne spójność, jeśli wiele wstawek może się zdarzyć jednocześnie lub jeśli chcesz zezwolić na powtarzanie nazw itp. Jednak w oparciu o przykład, który podałeś i szczegóły do ​​tej pory, ta metoda powinna działać.

+0

Tak, to jest automatycznie generowane – Youssef

0

Zakładając, że możesz ustawić AddressId, jakkolwiek chcesz ...

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 

Jeśli AddressId jest kolumną tożsamości, można tymczasowo wyłączyć tożsamość. Zobacz SET IDENTITY_INSERT, aby uzyskać informacje i przykłady.

2

To jest trochę hacky, ale robi to, co chcesz w dwóch oświadczeniach - zakładając, że żaden użytkownik nie będzie miał nazwy "abcd" lub wprowadzić tego dla swojego kraju, i że wyczyścisz tabelę NewUsers po tej operacji:

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 Chłodne użycie klauzuli "WYJŚCIE" :) – mellamokb

2

Państwo musi napisać kursor dla wstawić użytkowników i adres stół z Forign kluczowego

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

"Konieczność" to dość mocne słowo. Czy możesz wyjaśnić, dlaczego kursor jest jedyną opcją? –

0

Szczerze mówiąc, odpowiedź jest taka, że ​​nie chcesz robić to, co uważasz, że chcesz to zrobić. Jeśli użytkownicy mają jeden i tylko jeden adres, jak sam stwierdziłeś, powinieneś mieć tylko jedną tabelę (użytkowników) zawierającą pola adresu. Właściwe modelowanie danych sprawi, że problem ten zniknie samoistnie.

+0

Umieściłem tutaj tylko przykład, aby ludzie zrozumieli, czego potrzebuję. w rzeczywistości jest to o wiele bardziej skomplikowane i nie ma nic wspólnego z adresami i użytkownikami – Youssef

Powiązane problemy