我在网上看到oricle的merge例子,放到sql server 2008中就不行,好象SQL SERVER 2008 中merge不能
添加where 子句 特来向达人求证。

解决方案 »

  1.   

    没有,ORACLE不是SQL SERVER,两者还是有许多不同的。
      

  2.   

    merge 是SQL2008新增加的用法
    F1中:
              SQL Server 2008 联机丛书(2009 年 7 月)  
     
    MERGE (Transact-SQL)  发送反馈 
      请参阅    
     全部折叠全部展开 语言筛选器: 全部语言筛选器: 多个语言筛选器: Visual Basic语言筛选器: C#语言筛选器: C++语言筛选器: J#语言筛选器: JScript 
     
     Visual Basic(Declaration) 
     C#
     C++
     J#
     JScript根据与源表联接的结果,对目标表执行插入、更新或删除操作。例如,根据在另一个表中找到的差异在一个表中插入、更新或删除行,可以对两个表进行同步。 Transact-SQL 语法约定语法
     
    [ WITH <common_table_expression> [,...n] ]
    MERGE 
            [ TOP ( expression ) [ PERCENT ] ] 
            [ INTO ] <target_table> [ WITH ( <merge_hint> ) ] [ [ AS ] table_alias ]
            USING <table_source> 
            ON <merge_search_condition>
            [ WHEN MATCHED [ AND <clause_search_condition> ]
                THEN <merge_matched> ] [...n ]
            [ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]
                THEN <merge_not_matched> ]
            [ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]
                THEN <merge_matched> ] [...n ]
            [ <output_clause> ]
            [ OPTION ( <query_hint> [ ,...n ] ) ]    
    ;<target_table> ::=

        [ database_name . schema_name . | schema_name . ]
        target_table
    }<merge_hint>::=
    {
        { [ <table_hint_limited> [ ,...n ] ]
        [ [ , ] INDEX ( index_val [ ,...n ] ) ] }
    }<table_source> ::= 
    {
            table_or_view_name [ [ AS ] table_alias ] [ <tablesample_clause> ] 
                [ WITH ( table_hint [ [ , ]...n ] ) ] 
        | rowset_function [ [ AS ] table_alias ] 
                [ ( bulk_column_alias [ ,...n ] ) ] 
        | user_defined_function [ [ AS ] table_alias ]
        | OPENXML <openxml_clause> 
        | derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ] 
        | <joined_table> 
        | <pivoted_table> 
        | <unpivoted_table> 
    }<merge_search_condition> ::=
        <search_condition><merge_matched>::=
        { UPDATE SET <set_clause> | DELETE }<set_clause>::=
    SET
        { column_name = { expression | DEFAULT | NULL }
      | { udt_column_name.{ { property_name = expression
                                                  | field_name = expression }
                                                  | method_name ( argument [ ,...n ] ) }
         }
      | column_name { .WRITE ( expression , @Offset , @Length ) }
      | @variable = expression
      | @variable = column = expression
      | column_name { += | -= | *= | /= | %= | &= | ^= | |= } expression
      | @variable { += | -= | *= | /= | %= | &= | ^= | |= } expression
      | @variable = column { += | -= | *= | /= | %= | &= | ^= | |= } expression
      } [ ,...n ] <merge_not_matched>::=
    {
            INSERT [ ( column_list ) ] 
                { VALUES ( values_list )
                | DEFAULT VALUES }
    }<clause_search_condition> ::=
        <search_condition><search condition> ::=
            { [ NOT ] <predicate> | ( <search_condition> ) } 
            [ { AND | OR } [ NOT ] { <predicate> | ( <search_condition> ) } ] 
    [ ,...n ] <predicate> ::= 
        { expression { = | < > | ! = | > | > = | ! > | < | < = | ! < } expression 
        | string_expression [ NOT ] LIKE string_expression 
      [ ESCAPE 'escape_character' ] 
        | expression [ NOT ] BETWEEN expression AND expression 
        | expression IS [ NOT ] NULL 
        | CONTAINS 
        ( { column | * } , '< contains_search_condition >' ) 
        | FREETEXT ( { column | * } , 'freetext_string' ) 
        | expression [ NOT ] IN ( subquery | expression [ ,...n ] ) 
        | expression { = | < > | ! = | > | > = | ! > | < | < = | ! < } 
      { ALL | SOME | ANY} ( subquery ) 
        | EXISTS ( subquery ) } <output_clause>::=
    {
            [ OUTPUT <dml_select_list> INTO { @table_variable | output_table }
                [ (column_list) ] ]
        [ OUTPUT <dml_select_list> ]
    }<dml_select_list>::=
            { <column_name> | scalar_expression } 
                    [ [AS] column_alias_identifier ] [ ,...n ]<column_name> ::=
            { DELETED | INSERTED | from_table_name } . { * | column_name }
          | $action 参数
    WITH <common_table_expression>
    指定在 MERGE 语句作用域内定义的临时命名结果集或视图,也称为公用表表达式。该结果集派生自一个简单查询,并由 MERGE 语句引用。有关详细信息,请参阅 WITH common_table_expression (Transact-SQL)。TOP ( expression ) [ PERCENT ]
    指定受影响的行数或行百分比。expression 可以为行数,也可以为行百分比。在 TOP 表达式中引用的行不是以任意顺序排列的。有关详细信息,请参阅 TOP (Transact-SQL)。在联接整个源表和整个目标表并且删除了不符合插入、更新或删除操作条件的联接行之后,应用 TOP 子句。TOP 子句将联接行的数量进一步减少为指定值,并且以一种无序方式对其余联接行应用插入、更新或删除操作。也就是说,在 WHEN 子句中定义的操作中,这些行是无序分布的。例如,如果指定 TOP (10),将会影响 10 行;在这些行中,可能会更新 7 行而插入 3 行,或者可能删除 1 行、更新 5 行并且插入 4 行,等等。由于 MERGE 语句对源表和目标表都进行完全表扫描,因此在使用 TOP 子句通过创建多个批处理来修改大型表时,I/O 性能可能会受到影响。在这种情况下,一定要确保所有连续批处理都以新行作为处理目标。有关详细信息,请参阅优化 MERGE 语句性能。database_name 
    target_table 所在数据库的名称。schema_name 
    target_table 所属架构的名称。target_table 
    表或视图,<table_source> 中的数据行将根据 <clause_search_condition> 与该表或视图进行匹配。target_table 是由 MERGE 语句的 WHEN 子句指定的任何插入、更新或删除操作的目标。如果 target_table 为视图,则针对它的任何操作都必须满足更新视图所需的条件。有关详细信息,请参阅通过视图修改数据。target_table 不能是远程表。target_table 不能具有针对它定义的任何规则。[ AS ] table_alias
    用于引用表的替代名称。USING <table_source>
    指定基于 <merge_search condition> 与 target_table 中的数据行进行匹配的数据源。此匹配的结果指出了要由 MERGE 语句的 WHEN 子句采取的操作。<table_source> 可以是一个远程表,或者是一个能够访问远程表的派生表。<table_source> 可以是一个派生表,它使用 Transact-SQL 表值构造函数通过指定多行来构造表。有关此子句的语法和参数的详细信息,请参阅 FROM (Transact-SQL)。ON <merge_search_condition>
    指定在 <table_source> 与 target_table 进行联接以确定它们的匹配位置时所遵循的条件。注意: 
    重要的是,应仅指定目标表中用于匹配目的的列。也就是说,指定与源表中的对应列进行比较的目标表列。不要尝试通过在 ON 子句中筛选掉目标表中的行来提高查询性能,例如,指定 AND NOT target_table.column_x = value。这样做可能会返回意外和不正确的结果。
     
    WHEN MATCHED THEN <merge_matched>
    指定 target_table 中与 <table_source> ON <merge_search_condition> 返回的行匹配并满足所有其他搜索条件的所有行均应根据 <merge_matched> 子句进行更新或删除。MERGE 语句最多可以有两个 WHEN MATCHED 子句。如果指定了两个子句,则第一个子句必须同时带有一个 AND <search_condition> 子句。对于任何给定的行,只有在未应用第一个 WHEN MATCHED 子句的情况下,才会应用第二个 WHEN MATCHED 子句。如果有两个 WHEN MATCHED 子句,那么其中的一个必须指定 UPDATE 操作,而另一个必须指定 DELETE 操作。如果在 <merge_matched> 子句中指定了 UPDATE,并且根据 <merge_search_condition>,<table_source> 中的多个行与 target_table 中的某一行匹配,则 SQL Server 将返回错误。MERGE 语句无法多次更新同一行,也无法更新和删除同一行。WHEN NOT MATCHED [ BY TARGET ] THEN <merge_not_matched>
    指定对于 <table_source> ON <merge_search_condition> 返回的每一行,如果该行与 target_table 中的行不匹配但是满足其他搜索条件(如果存在),则在 target_table 中插入一行。要插入的值是由 <merge_not_matched> 子句指定的。MERGE 语句只能有一个 WHEN NOT MATCHED 子句。WHEN NOT MATCHED BY SOURCE THEN <merge_matched>
    指定 target_table 中与 <table_source> ON <merge_search_condition> 返回的行不匹配但满足所有其他搜索条件的所有行均应根据 <merge_matched> 子句进行更新或删除。MERGE 语句最多可以有两个 WHEN NOT MATCHED BY SOURCE 子句。如果指定了两个子句,则第一个子句必须同时带有一个 AND <clause_search_condition> 子句。对于任何给定的行,只有当未应用第一个 WHEN NOT MATCHED BY SOURCE 子句时才会应用第二个子句。如果有两个 WHEN NOT MATCHED BY SOURCE 子句,那么其中的一个必须指定 UPDATE 操作,而另一个必须指定 DELETE 操作。在 <clause_search_condition> 中只能引用目标表中的列。当 <table_source> 未返回任何行时,无法访问源表中的列。如果 <merge_matched> 子句中指定的更新或删除操作引用了源表中的列,将返回错误 207(无效列名)。例如,由于无法访问源表中的 Col1,因此 WHEN NOT MATCHED BY SOURCE THEN UPDATE SET TargetTable.Col1 = SourceTable.Col1 子句可能导致该语句失败。AND <clause_search_condition>
    指定任何有效的搜索条件。有关详细信息,请参阅搜索条件 (Transact-SQL)。<table_hint_limited>
    为由 MERGE 语句执行的每个插入、更新或删除操作指定对目标表应用的一个或多个表提示。需要有 WITH 关键字和括号。不允许使用 NOLOCK 和 READUNCOMMITTED。有关表提示的详细信息,请参阅表提示 (Transact-SQL)。对作为 INSERT 语句目标的表指定 TABLOCK 提示与指定 TABLOCKX 提示具有相同的效果。对表采用排他锁。如果指定了 FORCESEEK,会将其应用于与源表联接的目标表的隐式实例。注意: 
    指定带有 WHEN NOT MATCHED [ BY TARGET ] THEN INSERT 的 READPAST 可能会导致违反 UNIQUE 约束的 INSERT 操作。
     
    INDEX ( index_val [,...n ] )
    指定目标表上的一个或多个索引的名称或 ID,以执行与源表的隐式联接。有关详细信息,请参阅表提示 (Transact-SQL)。<output_clause>
    不按照任何特定顺序为 target_table 中更新、插入或删除的每一行返回一行。有关此子句的参数的详细信息,请参阅 OUTPUT 子句 (Transact-SQL)。OPTION ( <query_hint> [ ,...n ] )
    指定使用优化器提示来自定义数据库引擎处理语句的方式。有关详细信息,请参阅查询提示 (Transact-SQL)。<merge_matched>
    指定更新或删除操作,这些操作应用于 target_table 中与 <table_source> ON <merge_search_condition> 返回的行不匹配但满足所有其他搜索条件的所有行。UPDATE SET <set_clause>
    指定目标表中要更新的列或变量名的列表,以及用于更新它们的值。有关该子句的参数的详细信息,请参阅 UPDATE (Transact-SQL)。不允许将变量设置为与列相同的值。DELETE
    指定删除与 target_table 中的行匹配的行。
    <merge_not_matched>
    指定要插入到目标表中的值。( column_list )
    要在其中插入数据的目标表中的一列或多列的列表。必须使用单一部分名称格式来指定这些列,否则 MERGE 语句将失败。column_list 必须用圆括号括起来,并用逗号进行分隔。VALUES ( values_list )
    一个逗号分隔列表,其中包含常量、变量或者返回要插入到目标表中的值的表达式。表达式不能包含 EXECUTE 语句。DEFAULT VALUES
    强制插入的行包含为每个列定义的默认值。有关此子句的详细信息,请参阅 INSERT (Transact-SQL)。<search condition>
    指定用于指定 <merge_search_condition> 或 <clause_search_condition> 的搜索条件。有关此子句的参数的详细信息,请参阅搜索条件 (Transact-SQL)。注释
    必须指定三个 MATCHED 子句中的至少一个子句,但可以按任何顺序指定。不能在同一个 MATCHED 子句中多次更新一个变量。由 MERGE 语句指定的目标表中的任何插入、更新或删除操作都受为它定义的任何约束的限制,包括任何级联引用完整性约束。如果 IGNORE_DUP_KEY 对于目标表中的任何唯一索引都设置为 ON,则 MERGE 将忽略此设置。MERGE 语句需要一个分号 (;) 作为语句终止符。如果运行没有终止符的 MERGE 语句,将引发错误 10713。如果在 MERGE 之后使用,@@ROWCOUNT (Transact-SQL) 会返回为客户端插入、更新和删除的行的总数。在数据库兼容级别设置为 100 时,MERGE 为完全保留的关键字。MERGE 语句可用于设置为 90 和 100 的数据库兼容级别;但是,在将数据库兼容级别设置为 90 时,MERGE 为非完全保留的关键字。触发器的实现
    对于在 MERGE 语句中指定的每个插入、更新或删除操作,SQL Server 都会激发针对目标表定义的任何对应的 AFTER 触发器,但不保证哪个操作最先或最后激发触发器。为相同操作定义的触发器会遵循您指定的顺序进行触发。有关设置触发器激发顺序的详细信息,请参阅指定第一个和最后一个触发器。对于由 MERGE 语句执行的插入、更新或删除操作,如果目标表具有针对自己定义的已启用 INSTEAD OF 触发器,那么对于在 MERGE 语句中指定的所有操作,它都必须具有已启用的 INSTEAD OF 触发器。如果对 target_table 定义了任何 INSTEAD OF UPDATE 或 INSTEAD OF DELETE 触发器,则不会执行更新或删除操作,而是会激发触发器并相应地填充 inserted 和 deleted 表。如果对 target_table 定义了任何 INSTEAD OF INSERT 触发器,则不会执行插入操作,而是会激发触发器并相应地填充 inserted 表。权限
    需要对源表的 SELECT 权限和对目标表的 INSERT、UPDATE 或 DELETE 权限。有关其他信息,请参阅 SELECT、INSERT、UPDATE 和 DELETE 主题中的“权限”部分。
      

  3.   


    示例
    A. 使用 MERGE 在单个语句中对表执行 INSERT 和 UPDATE 操作
    一种常见的应用场景是在存在匹配行时更新表中的一个或多个列,或在不存在匹配行时将数据作为新行插入。此操作一般通过将参数传递给包含相应 UPDATE 和 INSERT 语句的存储过程来执行。借助 MERGE 语句,将可以在单个语句中一起执行这两项任务。下面的示例显示了一个同时包含 INSERT 语句和 UPDATE 语句的存储过程。随后,此示例对该过程进行了修改,以使用单个 MERGE 语句执行等效的操作。B. 使用 MERGE 在单个语句中对表执行 UPDATE 和 DELETE 操作
    下面的示例使用 MERGE 根据 SalesOrderDetail 表中已处理的订单,每天更新 AdventureWorks 示例数据库中的 ProductInventory 表。通过减去每天对 SalesOrderDetail 表中的每种产品所下的订单数,更新 ProductInventory 表的 Quantity 列。如果某种产品的订单数导致该产品的库存量下降到 0 或更少,则会从 ProductInventory 表中删除该产品对应的行。C. 借助派生的源表,使用 MERGE 对目标表执行 UPDATE 和 INSERT 操作
    下面的示例使用 MERGE 以更新或插入行的方式来修改 SalesReason 表。当源表中的 NewName 值与目标表 (SalesReason) 的 Name 列中的值匹配时,就会更新此目标表中的 ReasonType 列。当 NewName 的值不匹配时,就会将源行插入到目标表中。此源表是一个派生表,它使用 Transact-SQL 表值构造函数指定源表的多个行。有关在派生表中使用表值构造函数的详细信息,请参阅表值构造函数。该示例还说明了如何在表变量中存储 OUTPUT 子句的结果,并且说明存储结果之后如何通过执行返回已插入和更新的行的计数的简单选择操作来汇总 MERGE 语句的结果。D. 将 MERGE 语句的执行结果插入到另一个表中
    下面的示例捕获从 MERGE 语句的 OUTPUT 子句返回的数据,并将该数据插入到另一个表中。MERGE 语句根据在 SalesOrderDetail 表中处理的订单更新 ProductInventory 表的 Quantity 列。本示例捕获已更新的行并将这些行插入到用于跟踪库存变化的另一个表中。有关其他示例,请参阅使用 MERGE 插入、更新和删除数据和优化 MERGE 语句性能。请参阅
    参考
    SELECT (Transact-SQL)
    INSERT (Transact-SQL)
    UPDATE (Transact-SQL)
    DELETE (Transact-SQL)
    OUTPUT 子句 (Transact-SQL)
    FROM (Transact-SQL)其他资源
    使用 MERGE 插入、更新和删除数据
    在 Integration Services 包中使用 MERGE
    优化 MERGE 语句性能
    帮助和信息 
    获取 SQL Server 2008 帮助 文档反馈
    Microsoft 非常重视您的反馈。 若要对此主题进行评级并将有关此主题的反馈发送至文档小组,请单击一个等级,然后单击“发送反馈”。 有关支持问题的帮助信息,请参阅产品附带的技术支持信息。
    较差 1
     2
     3
     4
     5
     非常好 
    若要将您的反馈通过电子邮件发送至 Microsoft,请单击此处:    
    © 2009 Microsoft Corporation。保留所有权利。 
      

  4.   

    例子我写得有
    ---create table t1(col1 int,col2 varchar(20))
    create table t2(col1 int,col2 varchar(20),col3 date)
    go
    insert into t1 values --目标表
    (1,'aaa1')
    ,(2,'aaa2')
    ,(3,'aaa3')
    ,(6,'aaa6')insert into t2 values --源表
    (1,'bbb1',GETDATE())
    ,(2,'bbb2',GETDATE())
    ,(4,'bbb4',GETDATE())
    ,(5,'bbb5',GETDATE())
    go
    --
    merge t1 using t2 
    on t1.col1=t2.col1
    when matched then update set t1.col2=t2.col2
    when not matched then insert values(t2.col1,t2.col2)
    when not matched by source then delete;
    go
    select * from t1
    drop table t1,t2--结果把目标数据换成了源表数据
      

  5.   

    参考:
    解读SQL Server2008的新语句MERGE作者:Jonathan Allen  2007-07-24     SQL Server 2008将包含用于合并两个行集(rowset)数据的新句法。根据一个源数据表对另一个数据表进行确定性的插入、更新和删除这样复杂的操作,运用新的MERGE语句,开发者用一条命令就可以完成。     对两个表进行信息同步时,有三步操作要进行。首先要处理任何需要插入目标数据表的新行。其次是处理需要更新的已存在的行。最后要删除不再使用的旧行。这个过程中需要维护大量重复的逻辑,并可能导致微妙的错误。     Bob Beauchemin讨论了MERGE语句,这个语句将上述的多个操作步骤合并成单一语句。他给出了如下的例子: merge [target] t
    using [source] s on t.id = s.id
    when matched then update t.name = s.name, t.age = s.age -- use "rowset1"
    when not matched then insert values(id,name,age) -- use "rowset2"
    when source not matched then delete; -- use "rowset3"     如你所见,具体操作是根据后面的联合(join)的解析结果来确定的。在这个例子中,如果目标和源数据表有匹配的行,就实行更新操作。如果没有,就实行插入或者删除操作来使目标数据表和源数据表保持一致。     这个新句法的一个美妙之处是它在处理更新时的确定性。在使用标准的UPDATE句法和联合时,可能有超过一个源行跟目标行匹配。在这种情况下,无法预料更新操作会采用哪个源行的数据。     而当使用MERGE句法时,如果存在多处匹配,它会抛出一个错误。这就提醒了开发者,要达到预想的目标,当前的联合条件还不够明确。 SQL Server 2008 MERGE
    ZDNet 软件频道 更新时间:2007-11-19 作者:David.Portas 来源:David Portas’ Blog
    本文关键词:MERGE SQL Server 2008 SQL Server 数据库 
    MERGE is a new DML statement in SQL Server 2008. Microsoft have implemented the ISO SQL 2003 and 2007 standard MERGE statement (as seen in Oracle and DB2) and added some extensions of their own.In a nutshell, MERGE allows you to perform simultaneous UPDATE, INSERT and/or DELETE operations on one table. There are new physical operators that combine these operations so that they can be performed in a single scan rather than multiple scans.MERGE has loads of possible applications. For the first time you can assign the contents of one table or query to another in a single operation. The following example requires SQL Server 2008 CTP4. Given this schema and data:CREATE TABLE a
     (keycol INT PRIMARY KEY,
      col1 INT NOT NULL,
      col2 INT NOT NULL,
      col3 INT NOT NULL);CREATE TABLE b
     (keycol INT PRIMARY KEY,
      col1 INT NOT NULL,
      col2 INT NOT NULL,
      col3 INT NOT NULL);INSERT INTO a VALUES (1,0,0,0),(2,0,0,0);
    INSERT INTO b VALUES (1,1,1,1),(3,3,3,3);The following MERGE will populate table a with the same data as table b:MERGE INTO a
    USING b
     ON a.keycol = b.keycol
    WHEN MATCHED THEN
     UPDATE SET
      col1 = b.col1,
      col2 = b.col2,
      col3 = b.col3
    WHEN NOT MATCHED THEN
     INSERT (keycol, col1, col2, col3)
     VALUES (b.keycol, b.col1, b.col2, b.col3)
    WHEN SOURCE NOT MATCHED THEN
     DELETE;In the relational world this is the operation known as Relational Assignment ie: a := bUnfortunately the SQL syntax is less pretty and requires just a little more typing!MERGE also makes a good "upsert" for application CRUD stored procedures, removing the need for constructs like:IF NOT EXISTS ...
      INSERT ...Here's an example I created today. It inserts a new Vendor if and only if the name doesn't already exist. Whether the name previously existed or not, it returns the IDENTITY value of the existing or newly inserted row.CREATE PROC dbo.usp_VendorUpsert(     @pVendorID INT OUTPUT,     @pVendorName VARCHAR(80)) ASBEGIN      SET NOCOUNT ON;      MERGE dbo.Vendor t     USING (SELECT @pVendorName            ) p(VendorName)     ON t.VendorName = @pVendorName      WHEN NOT MATCHED THEN     INSERT (VendorName)     VALUES (@pVendorName)      WHEN MATCHED THEN     UPDATE SET @pVendorID = VendorID;      SET @pVendorID = COALESCE(SCOPE_IDENTITY(),@pVendorID); END RETURN It's amazing that it took nearly 20 years for the SQL standards committee to come up with MERGE. Perhaps the delay is a legacy of the decision to make INSERT, UPDATE and DELETE the basic data update operators. INSERT, UPDATE and DELETE can all be defined as different kinds of relational assignment - assignment being the most basic type of update possible. So arguably MERGE is the more primitive and fundamental data update operator that ought to have been around earlier rather than later.