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 变量以查找刚刚插入的记录。
如果记录存在,我必须编写一个程序来更新 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 变量以查找刚刚插入的记录。