Geo*_*rge 5 t-sql sql-server merge upsert sql-server-2008
我已经" 继承了 "一条出色的TSQL代码:
显然这很糟糕(性能和优雅的原因)!!
问题 首先,这看起来像MERGE使用的标准情况.我试过做:
MERGE [dbo].[TableA] AS Target
USING <cursor data set as a select statement> as Src on target.IDA = Src.IDA
WHEN MATCHED
//update
WHEN NOT MATCHED
//insert <------ Fails because obviously a new IDB is required
Run Code Online (Sandbox Code Playgroud)
还尝试了各种方法,nested select that sends IDB on the OUTPUT但它失败了,因为IDB是PK.
其他类型的合并也失败了,例如:
MERGE Table A with <cursor data set as a select statement>
...
MERGE Table A with Table B
WHEN NOT MATCHED
//insert on Table A
WHEN NOT MATCHED
// Update Table B
Run Code Online (Sandbox Code Playgroud)
有没有人对此有所了解?基本上我认为如果我们推广这个问题将是:
Can I insert and return the PK in one statement that can be nested in other statements
提前感谢您的回复
乔治
如果您在 TableB 上有自动生成的 PK,则可以使用与此类似的代码。否则,只需将 INSERT 更改为 TableA,即可先从 TableB 中获取 PK。
DECLARE @OldData CHAR(10)
SET @OldData = 'Old'
DECLARE @NewData CHAR(10)
SET @NewData = 'New'
CREATE TABLE #TableA
(
IDA INT IDENTITY(1,1) PRIMARY KEY,
IDB INT NOT NULL,
DataA CHAR(10)
)
CREATE TABLE #TableB
(
IDB INT IDENTITY(1,1) PRIMARY KEY,
DataB CHAR(10)
)
DECLARE @IDsToUpsert TABLE
(
ID INT
)
-- Add test values for existing rows
INSERT INTO #TableB
OUTPUT INSERTED.IDB, @OldData
INTO #TableA
SELECT @OldData UNION ALL
SELECT @OldData UNION ALL
SELECT @OldData UNION ALL
SELECT @OldData
-- Add test values for the rows to upsert
INSERT INTO @IDsToUpsert
SELECT 1 UNION -- exists
SELECT 3 UNION -- exists
SELECT 5 UNION -- does not exist
SELECT 7 UNION -- does not exist
SELECT 9 -- does not exist
-- Data Before
SELECT * From #TableA
SELECT * From #TableB
DECLARE rows_to_update CURSOR
FOR SELECT ID FROM @IDsToUpsert
DECLARE @rowToUpdate INT
DECLARE @existingIDB INT
OPEN rows_to_update;
FETCH NEXT FROM rows_to_update
INTO @rowToUpdate;
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRANSACTION
IF NOT EXISTS
(
SELECT 1 FROM #TableA WITH (UPDLOCK, ROWLOCK, HOLDLOCK)
WHERE IDA = @rowToUpdate
)
BEGIN
-- Insert into B, then insert new val into A
INSERT INTO #TableB
OUTPUT INSERTED.IDB, INSERTED.DataB
INTO #TableA
SELECT @NewData
-- Change code here if PK on TableB is not autogenerated
END
ELSE
BEGIN
-- Update
UPDATE #TableA
SET DataA = @NewData
WHERE IDA = @rowToUpdate
END
COMMIT TRANSACTION
FETCH NEXT FROM rows_to_update
INTO @rowToUpdate;
END
CLOSE rows_to_update;
DEALLOCATE rows_to_update;
SELECT * FROM #TableA
SELECT * FROM #TableB
DROP TABLE #TableA
DROP TABLE #TableB
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2104 次 |
| 最近记录: |