【问题标题】:SQL Server 2008: Update/Insert data(multiple records) from multiple columns of different tablesSQL Server 2008:从不同表的多列更新/插入数据(多条记录)
【发布时间】:2016-02-09 02:55:15
【问题描述】:



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

表设计:

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]

更新/插入代码

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;

任何帮助将不胜感激。

【问题讨论】:

    标签: sql-server sql-server-2008 sql-update multiple-columns sql-insert


    【解决方案1】:

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

    假设您必须有四个单独的表(临时表),这是一种方法。我向表变量添加了自动增量主键,以使连接数据更加直接。

    您还可以使用 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) 如果您需要获取插入的标识值列表,请在插入的脚本之前声明一个表变量(以获取所有 ID 的行):

    DECLARE @myIDs table (ID int);
    

    然后在插入语句中使用 OUTPUT 子句(如果 ID 是您的键列):

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

    然后您可以将其他查询(更新、选择等)加入到表变量中以查找刚刚插入的记录。

    【讨论】:

    • 如何获取所有插入行的生成标识值?
    • 谢谢。我无法使用 row_num 更新记录。在此之后我面临另一个问题。你能看看follow-up question 并提出一些建议吗?谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多