Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用复合主键从另一个表插入或更新表_Sql_Sql Server_Sql Server 2005 - Fatal编程技术网

Sql 使用复合主键从另一个表插入或更新表

Sql 使用复合主键从另一个表插入或更新表,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我正在寻找从SQL直接执行以下操作的正确语法和方法:插入或更新(如果数据已经存在)TableMain来自TableA中包含的数据,两者都具有相同的复合主键 两个表的定义如下: CREATE TABLE TableA ( [TID0] [int] NOT NULL, [TID1] [int] NOT NULL, [language] [nvarchar](2) NOT NULL, [TID2] [nvarchar](200) NOT NULL, [text] [nvarchar](max) NUL

我正在寻找从SQL直接执行以下操作的正确语法和方法:插入或更新(如果数据已经存在)
TableMain
来自
TableA
中包含的数据,两者都具有相同的复合主键

两个表的定义如下:

CREATE TABLE TableA (
[TID0] [int] NOT NULL,
[TID1] [int] NOT NULL,
[language] [nvarchar](2) NOT NULL,
[TID2] [nvarchar](200) NOT NULL,
[text] [nvarchar](max) NULL,
[updatedOn] [datetime] NOT NULL  DEFAULT (getdate())
PRIMARY KEY (
    [TID0],
    [TID1],
    [language],
    [TID2],
)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
表A
将定期删除和填写

TableMain
与定义相同,但将包含更多的数据行,我需要的是将从未见过的值从
TableA
插入
TableMain
,并更新已有的行

我曾经做过这种插入,但我不知道如何处理更新和复合主键:

INSERT INTO TableMain 
    SELECT * FROM TableA
编辑:我正在使用SQL Server 9.00.5000

编辑:另一种受合并和

您可以使用SQLServer2008中的命令。它允许您将另一个数据源中的数据合并到主数据源中,并在存在键匹配(您可能希望更新表)或不匹配且希望插入新记录时定义特定行为

您可以访问此链接以获取少量代码示例。

您应该使用station

大概是这样的:

merge TableMain  AS target
using TableA as source 
ON <join tables here>
WHEN MATCHED THEN <update>
WHEN NOT MATCHED BY TARGET <Insert>
WHEN NOT MATCHED BY SOURCE <delete>
merge TableMain作为目标
使用TableA作为源
在…上
当匹配时
当目标不匹配时
当源不匹配时

以下是一个脚本,您可以使用它来升级数据:

-- On error transaction is automatically rolled back
set xact_abort on

begin transaction
-- First update records
update TableMain
   set [text]      = source.[text],
       [updatedOn] = source.[updatedOn]
  from TableMain
 inner join TableA source
    on TableMain.[TID0]     = source.[TID0]
   and TableMain.[TID1]     = source.[TID1]
   and TableMain.[language] = source.[language]
   and TableMain.[TID2]     = source.[TID2]

-- And then insert

insert into TableMain ([TID0], [TID1], [language], [TID2], [text], [updatedOn])
select [TID0], [TID1], [language], [TID2], [text], [updatedOn]
  from TableA source
 where not exists
       (
          select *
            from TableMain
           where TableMain.[TID0]     = source.[TID0]
             and TableMain.[TID1]     = source.[TID1]
             and TableMain.[language] = source.[language]
             and TableMain.[TID2]     = source.[TID2]
       )

commit transaction

您可以将notexists()重写为
左连接。。。其中TableMain.TID0为空
如果性能不令人满意。

非常有趣,我不知道合并语句BTW看起来像我的SQL Server 2005不接受它:/SQLServer2008发布的合并语句。如果您使用的是2005版本,我想您必须使用旧的方法来检查是否存在,并应用相关的行为。合并功能非常强大,承诺了原子性、性能和许多其他优点。谢谢,顺便说一句,其他答案也帮助我找到了使用输出子句的另一种工作方式(我以前也不知道:)。。。几乎他和你的想法一样,把东西放在一个声明的表格里看:我不知道什么是更有效的方法…附言:我还为将来添加了另一种方法,如果它能帮助某人的话else@user1340802输出方式正确且可能更快,因为所有未更新的源记录都是新的,人们不必在可能大得多的源表中搜索匹配项,但缺少实现。表变量
@updatedIDs
应具有主键(TID0、TID1、language、TID2)以提高效率,否则Sql Server假定它包含一行,因为未收集表变量的统计信息。应按选择性顺序列出色谱柱-首先列出选择性最高的色谱柱。这也适用于TableA。感谢您的帮助,在文本中添加了主键!是的,但目前我问他在这个问题上没有SQL2005标记:)
-- On error transaction is automatically rolled back
set xact_abort on

begin transaction
-- First update records
update TableMain
   set [text]      = source.[text],
       [updatedOn] = source.[updatedOn]
  from TableMain
 inner join TableA source
    on TableMain.[TID0]     = source.[TID0]
   and TableMain.[TID1]     = source.[TID1]
   and TableMain.[language] = source.[language]
   and TableMain.[TID2]     = source.[TID2]

-- And then insert

insert into TableMain ([TID0], [TID1], [language], [TID2], [text], [updatedOn])
select [TID0], [TID1], [language], [TID2], [text], [updatedOn]
  from TableA source
 where not exists
       (
          select *
            from TableMain
           where TableMain.[TID0]     = source.[TID0]
             and TableMain.[TID1]     = source.[TID1]
             and TableMain.[language] = source.[language]
             and TableMain.[TID2]     = source.[TID2]
       )

commit transaction