Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.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 在UPDATE语句中使用将未提交的数据更新到单元格_Sql_Sql Server_Performance_Sql Update_Isolation Level - Fatal编程技术网

Sql 在UPDATE语句中使用将未提交的数据更新到单元格

Sql 在UPDATE语句中使用将未提交的数据更新到单元格,sql,sql-server,performance,sql-update,isolation-level,Sql,Sql Server,Performance,Sql Update,Isolation Level,我想在SQLServer2008中将存储在名称-值对数据中的表转换为关系形式 源表 Strings ID Type String 100 1 John 100 2 Milton 101 1 Johny 101 2 Gaddar 目标要求 Customers ID FirstName LastName 100 John Milton 101 Johny Gaddar 我遵循下面给出的策略 使用字符串表中的ID值填充客户表 INSERT I

我想在SQLServer2008中将存储在名称-值对数据中的表转换为关系形式

源表

Strings
ID  Type    String
100 1   John
100 2   Milton
101 1   Johny
101 2   Gaddar
目标要求

Customers
ID  FirstName   LastName
100 John        Milton
101 Johny       Gaddar
我遵循下面给出的策略

使用字符串表中的ID值填充客户表

INSERT INTO CUSTOMERS SELECT DISTINCT ID FROM Strings
你会得到以下结果

Customers
ID  FirstName   LastName
100 NULL        NULL
101 NULL        NULL
通过使用ID列将其连接到字符串,使用其余属性更新客户。这样,Customers中的每条记录都将有相应的2条匹配记录

UPDATE Customers
    SET FirstName = (CASE WHEN S.Type=1 THEN S.String ELSE FirstName)
        LastName = (CASE WHEN S.Type=2 THEN S.String ELSE LastName)
FROM Customers
    INNER JOIN Strings ON Customers.ID=Strings.ID
中间状态将类似于

ID  FirstName   LastName    ID  Type    String
100 John        NULL        100 1   John
100 NULL        Milton      100 2   Milton
101 Johny       NULL        101 1   Johny
101 NULL        Gaddar      101 2   Gaddar
但这并不像预期的那样有效。因为在
SET
子句中赋值时,它只设置提交的值,而不是未提交的值。在
UPDATE
语句中是否仍然可以设置未提交的值(在查询的处理时间内)


PS:我不是在寻找替代解决方案,而是通过告诉SQL Server使用未提交的数据进行
更新来实现我的方法。最简单的方法是将更新分为两部分:

UPDATE Customers
SET FirstName = Strings.String
FROM Customers
INNER JOIN Strings ON Customers.ID=Strings.ID AND Strings.Type = 1
然后:

UPDATE Customers
SET LastName = Strings.String
FROM Customers
INNER JOIN Strings ON Customers.ID=Strings.ID AND Strings.Type = 2

在一个查询(例如派生表)中可能有一些方法可以实现这一点,但除非这是一个特定的要求,否则我只会使用这种方法。

看看这个方法,它应该可以避免您执行的所有步骤

DECLARE @Table TABLE(
        ID INT,
        Type INT,
        String VARCHAR(50)
)
INSERT INTO @Table (ID,[Type],String) SELECT 100 ,1   ,'John'
INSERT INTO @Table (ID,[Type],String) SELECT 100 ,2   ,'Milton'
INSERT INTO @Table (ID,[Type],String) SELECT 101 ,1   ,'Johny'
INSERT INTO @Table (ID,[Type],String) SELECT 101 ,2   ,'Gaddar'

SELECT  IDs.ID,
        tName.String NAME,
        tSur.String Surname
FROM    (
            SELECT DISTINCT ID
            FROM @Table
        ) IDs LEFT JOIN
        @Table tName ON IDs.ID = tName.ID AND tName.[Type] = 1  LEFT JOIN
        @Table tSur ON IDs.ID = tSur.ID AND tSur.[Type] = 2
好吧,我不认为你会找到一个解决你所寻找的问题的办法。从它的国家

在FROM子句中使用UPDATE

UPDATE语句的结果如下 如果语句包含 中未指定的FROM子句 只有一个值是可用的 可用于每个列引用 即更新,即如果更新 语句是不确定的。对于 例如,在中的UPDATE语句中 以下脚本中的两行 表1符合本公司的资质要求 UPDATE语句中的FROM子句; 但它不确定从哪一行开始 表1用于更新中的行 表2

阿斯坦德是正确的(我接受他的回答)更新不是因为读取未提交问题,而是因为联接返回了多行。我已经验证了这一点。UPDATE仅拾取从多条记录生成的第一行以更新原始表。这是MSSQL、Sybase等RDMBMSs的行为,但Oracle不允许这种更新,并且会抛出错误。我已经为MSSQL验证了这个东西

同样,MSSQL不支持使用未提交的数据更新单元格。不知道其他RDBMS的状态。我不知道任何RDBMS是否提供了查询隔离级别管理

另一种解决方案是分两步完成,聚合到unpivot,然后插入。与上述答案中给出的方法相比,这种方法的扫描次数较少

INSERT INTO Customers
SELECT 
    ID
    ,MAX(CASE WHEN Type = 1 THEN String ELSE NULL END) AS FirstName
    ,MAX(CASE WHEN Type = 2 THEN String ELSE NULL END) AS LastName
FROM Strings
GROUP BY ID 

感谢我的朋友罗吉·托马斯帮了我这个忙。

这和答案1是一样的。您使用的是多个联接,而不是单独进行更新。这也将导致对字符串表进行多次扫描,我希望避免这种情况。我不是在寻找替代解决方案,而是通过告诉SQL Server使用未提交的数据来实现我的方法。无论如何,谢谢你。感谢您的努力:)您看过READUNCOMMITTED提示吗?我尝试将语句上方的隔离级别设置为READ UNCOMMITTED,但没有任何区别(将事务隔离级别设置为READ UNCOMMITTED;)。我认为它不会对“查询中的更改”和Microsoft文档产生任何影响[说“不允许使用NOLOCK和READUNCOMMITED”这是我以前使用的方法。我想用它来保存字符串表上的扫描,因为它有数百万条记录。
INSERT INTO Customers
SELECT 
    ID
    ,MAX(CASE WHEN Type = 1 THEN String ELSE NULL END) AS FirstName
    ,MAX(CASE WHEN Type = 2 THEN String ELSE NULL END) AS LastName
FROM Strings
GROUP BY ID