SQL Server 2008: Update/Insert 来自不同表的多个列的数据(多条记录)

SQL Server 2008: Update/Insert data(multiple records) from multiple columns of different tables



如果记录存在,我必须编写一个程序来更新 table,否则插入数据。我从不同的列中获取以逗号分隔的字符串形式的记录。
例如:
ID = "2,3,4,5";
名字 = "S,D,G,H";
我采用的方法是:创建 ID Table 和名称 Table,每个都有一列。 (正在使用拆分函数,returns table 具有包含值的单列)。然后我正在尝试 insert/update 数据。插入工作正常。但是对于更新记录,它正在更新不正确的值。
我是 SQL 的新手,无法解决我做错了什么或者我的方法是否合适!请帮忙。请注意,在我的方法中,我使用 row_num 从不同的温度 table 中以正确的顺序选择记录。以下是我的代码:

Table设计:

CREATE TABLE [dbo].[TestMultipleInsert](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    [Number] [int] NOT NULL,
    [Number1] [int] NULL,
 CONSTRAINT [PK_TestMultipleInsert] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

代码 Update/Insert

declare @names table (name varchar(50));  --Consider as split string values of Name Column
declare @numbers table (phone int); -- Consider as split string values of Number column
declare @number1s table (phone1 int); -- Consider as split string values of Number1 column
declare @MCodes table (Id int); --Consider as split string values of Id column. If Id = -1, then it's a new entry, else updated record.


-- Insert test data for running query
insert into @names (name) values('First');
insert into @names (name) values('Second');
insert into @names (name) values('Third');
insert into @names (name) values('Fourth');

insert into @numbers (phone) values(112);
insert into @numbers (phone) values(399);
insert into @numbers (phone) values(499);
insert into @numbers (phone) values(499);

insert into @number1s (phone1) values(112);
insert into @number1s (phone1) values(299);
insert into @number1s (phone1) values(399);
insert into @number1s (phone1) values(399);

insert into @MCodes (Id) values(54); --Update
insert into @MCodes (Id) values(-1); --Insert
insert into @MCodes (Id) values(50); --Update
insert into @MCodes (Id) values(-1); --Insert

--Query
insert into dbo.TestMultipleInsert (Name, Number, Number1)
select A.name, B.phone, C.phone1
from(
    SELECT name,row_number() over (order by (select 0)) as row_num
    FROM @names)A,
    (SELECT phone,row_number() over (order by (select 0)) as row_num
    FROM @numbers)B,
    (SELECT phone1,row_number() over (order by (select 0)) as row_num
    FROM @number1s)C,
    (SELECT Id,row_number() over (order by (select 0)) as row_num
    FROM @MCodes)D
where  A.row_num=B.row_num  and A.row_num = C.row_num  and D.row_num = A.row_num and D.Id = -1

Update dbo.TestMultipleInsert 
SET Name=A.Name, Number =B.phone, Number1= C.phone1
from(
    SELECT name,row_number() over (order by (select 0)) as row_num
    FROM @names)A,
    (SELECT phone,row_number() over (order by (select 0)) as row_num
    FROM @numbers)B,
    (SELECT phone1,row_number() over (order by (select 0)) as row_num
    FROM @number1s)C,
(SELECT Id,row_number() over (order by (select 0)) as row_num
    FROM @MCodes)D
    where  D.row_num=B.row_num  and D.row_num = C.row_num  and D.row_num = A.row_num and D.Id <> -1 and D.Id = dbo.TestMultipleInsert.Id

select * from dbo.TestMultipleInsert;

我们将不胜感激任何帮助。

A1) 我不知道你的大局是什么,但据我所知,你的脚本正在运行。 INSERT 正在插入我期望的内容,而 UPDATE 正在更新我期望的记录。使用 row_number() over() 函数在技术上没有任何问题,但我在下面建议的方式更直接一些。 (在这种情况下只是偏好)

假设您必须有四个独立的 tables (temp tables),这是一种方法。我向 table 变量添加了自动递增主键,以便更直接地连接数据。

您也可以使用 MERGE 语句一次性完成更新和插入。 (关于合并:https://msdn.microsoft.com/en-us/library/bb510625(v=sql.105).aspx

--added auto increment primary key to avoid using window function row_nmber() over()...
declare @names table (pkey int primary key identity,name varchar(50));  --Consider as split string values of Name Column
declare @numbers table (pkey int primary key identity, phone int); -- Consider as split string values of Numer column
declare @number1s table (pkey int primary key identity, phone1 int); -- Consider as split string values of Number1 column
declare @MCodes table (pkey int primary key identity,Id int); --Consider as split string values of Id column. If Id = -1, then it's a new entry, else updated record.


-- Insert test data for running query
insert into @names (name) values('First');
insert into @names (name) values('Second');
insert into @names (name) values('Third');
insert into @names (name) values('Fourth');

insert into @numbers (phone) values(112);
insert into @numbers (phone) values(399);
insert into @numbers (phone) values(499);
insert into @numbers (phone) values(499);

insert into @number1s (phone1) values(112);
insert into @number1s (phone1) values(299);
insert into @number1s (phone1) values(399);
insert into @number1s (phone1) values(399);

insert into @MCodes (Id) values(54);
insert into @MCodes (Id) values(-1);
insert into @MCodes (Id) values(50);
insert into @MCodes (Id) values(-1);

--Insert Query
INSERT INTO dbo.TestMultipleInsert (Name, Number, Number1)
SELECT A.name, B.phone, C.phone1
FROM @names A
    JOIN @numbers B ON B.pkey = A.pkey
    JOIN @number1s C ON C.pkey = A.pkey
    JOIN @MCodes D ON D.pkey = A.pkey
WHERE D.Id = -1

--Update query
UPDATE dbo.TestMultipleInsert 
SET Name = upd.Name
  , Number = upd.phone
  , Number1 = upd.phone1
FROM(
    SELECT A.name, B.phone, C.phone1, D.Id
    FROM @names A
        JOIN @numbers B on B.pkey = A.pkey
        JOIN @number1s C on C.pkey = A.pkey
        JOIN @MCodes D on D.pkey = A.pkey
    WHERE D.Id <> -1
    ) upd
WHERE upd.Id = dbo.TestMultipleInsert.Id

A2) 如果您需要获取插入的标识值列表,请在插入的脚本之前声明一个 table 变量(以获取所有 ID 的行):

DECLARE @myIDs table (ID int);

然后将 OUTPUT 子句与您的插入语句一起使用(如果 ID 是您的键列):

INSERT INTO tableBlah
OUTPUT INSERTED.ID INTO @myIDs
VALUES ...blah blah

然后您可以将其他查询(更新、select 等)加入 table 变量以查找刚刚插入的记录。