2012-05-24 37 views
7

Trong một DATABASE SQLSQL: Chèn dữ liệu từ bảng khác trong một bảng có chứa các phím nước ngoài

Tôi có một người sử dụng Bảng

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

đâu AddressID là khóa ngoại đến một bảng tên Địa chỉ

Các Addresses Bảng:

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

Đây là một one-to-ONE Mối quan hệ: Mỗi người dùng có 1 địa chỉ và mỗi địa chỉ có một người sử dụng

Tôi có một bảng mới có tên NEWUsers

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

Nó chỉ có Id và Tên.

Điều tôi muốn làm là:

Viết kịch bản để chèn tất cả các bản ghi Từ bảng NEWUSers vào bảng người dùng.

  • Tôi muốn The Age được mặc định 20 cho tất cả người dùng mới
  • Và đối với mỗi người dùng mới đưa tôi cần phải tạo ra một kỷ lục Địa chỉ mới cho anh ta
  • kỷ lục Địa chỉ mới sẽ có tất cả các giá trị của nó (đất nước, thành phố, tiểu bang, mã bưu điện) tương đương với "abcd" ngoại trừ Id mà sẽ được sử dụng để thiết lập các AddressID chính nước ngoài cho người dùng mới)

làm thế nào tôi có thể làm điều đó?

tôi thử như sau:

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

Nhưng tôi không biết làm thế nào để tạo ra một kỷ lục Địa chỉ mới cho mỗi người dùng chèn vào và xác định chính nước ngoài cho phù hợp.

Cảm ơn rất nhiều sự giúp đỡ nào

+0

là 'Adresses.Id' là' IDENTITY'? –

+0

để tạo địa chỉ mới khi bạn chèn mới 'Người dùng', bạn nên quyết định tạo' trình kích hoạt' sẽ được thực hiện sau khi bạn chèn Người dùng mới. – Sajmon

+0

@ypercube yes it is Identity – Youssef

Trả lời

6

Một phương pháp sẽ có hai truy vấn, được hình thành như sau:

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: Một cách đơn giản để kết nối người sử dụng với địa chỉ sẽ là để tạm thời đặt quốc gia thành tên người dùng. Sau đó, bạn sẽ có một liên kết để xác định addressId. Khi bảng người dùng là dân cư và liên kết lên đúng cách, bạn có thể thiết lập đất nước trở lại với giá trị mặc định 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

Có nhiều cách phức tạp hơn để làm điều này nếu bạn muốn đảm bảo giao dịch nhất quán nếu nhiều chèn có thể xảy ra đồng thời, hoặc nếu bạn muốn cho phép trùng lặp tên, vv Nhưng dựa trên ví dụ bạn đã đưa ra và chi tiết cho đến nay, phương pháp này sẽ làm việc.

+0

Có nó được tự động tạo ra – Youssef

0

Giả sử bạn có thể đặt AddressId theo cách bạn muốn ...

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 

Nếu AddressId là cột nhận dạng, bạn có thể tắt nhận dạng tạm thời trước. Xem SET IDENTITY_INSERT để biết thông tin và ví dụ.

2

Đây là một chút hacky, nhưng thực hiện những gì bạn muốn trong hai câu lệnh - giả sử không có người dùng nào có tên 'abcd' hoặc nhập tên cho quốc gia của họ và bạn thanh lọc bảng Người dùng mới sau thao tác này:

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 Sử dụng mát mẻ của mệnh đề 'OUTPUT' :) – mellamokb

2

bạn phải Viết Cursor Đối Insert Trong Users and Address Table với forign chính

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

" Phải "là một từ khá mạnh. Bạn có thể giải thích tại sao con trỏ là lựa chọn duy nhất không? –

0

Thành thực mà nói, câu trả lời là bạn không muốn làm những gì bạn nghĩ rằng bạn muốn làm. Nếu người dùng có một và chỉ một địa chỉ, như bạn đã nói, thì bạn chỉ nên có một bảng (người dùng) có chứa các trường địa chỉ. Việc mô hình hóa dữ liệu của bạn đúng cách sẽ làm cho vấn đề này biến mất về bản chất.

+0

Tôi chỉ đặt ở đây một ví dụ chỉ để mọi người hiểu những gì tôi cần. thực sự nó phức tạp hơn rất nhiều và điều này không liên quan gì đến Địa chỉ và Người dùng – Youssef

Các vấn đề liên quan