मेरे पास नीचे MERGE
बयान है जो डेटाबेस के खिलाफ जारी किया गया है:
MERGE "MySchema"."Point" AS t
USING (
SELECT "ObjectId", "PointName", z."Id" AS "LocationId", i."Id" AS "Region"
FROM @p1 AS d
JOIN "MySchema"."Region" AS i ON i."Name" = d."Region"
LEFT JOIN "MySchema"."Location" AS z ON z."Name" = d."Location" AND z."Region" = i."Id"
) AS s
ON s."ObjectId" = t."ObjectId"
WHEN NOT MATCHED BY TARGET
THEN INSERT ("ObjectId", "Name", "LocationId", "Region") VALUES (s."ObjectId", s."PointName", s."LocationId", s."Region")
WHEN MATCHED
THEN UPDATE
SET "Name" = s."PointName"
, "LocationId" = s."LocationId"
, "Region" = s."Region"
OUTPUT $action, inserted.*, deleted.*;
हालाँकि, यह सत्र निम्न त्रुटि के साथ समाप्त होने का कारण बनता है:
Msg 0, स्तर 11, राज्य 0, पंक्ति 67 वर्तमान आदेश पर एक गंभीर त्रुटि उत्पन्न हुई। यदि कोई परिणाम हैं, तो उनकी उपेक्षा की जानी चाहिए।
Msg 0, लेवल 20, स्टेट 0, लाइन 67 वर्तमान कमांड पर एक गंभीर त्रुटि हुई। यदि कोई परिणाम हैं, तो उनकी उपेक्षा की जानी चाहिए।
मैंने एक छोटी परीक्षण स्क्रिप्ट को एक साथ रखा है जो त्रुटि पैदा करती है:
USE master;
GO
IF DB_ID('TEST') IS NOT NULL
DROP DATABASE "TEST";
GO
CREATE DATABASE "TEST";
GO
USE "TEST";
GO
SET NOCOUNT ON;
IF SCHEMA_ID('MySchema') IS NULL
EXECUTE('CREATE SCHEMA "MySchema"');
GO
IF OBJECT_ID('MySchema.Region', 'U') IS NULL
CREATE TABLE "MySchema"."Region" (
"Id" TINYINT IDENTITY NOT NULL CONSTRAINT "PK_MySchema_Region" PRIMARY KEY,
"Name" VARCHAR(8) NOT NULL CONSTRAINT "UK_MySchema_Region" UNIQUE
);
GO
INSERT [MySchema].[Region] ([Name])
VALUES (N'A'), (N'B'), (N'C'), (N'D'), (N'E'), ( N'F'), (N'G');
IF OBJECT_ID('MySchema.Location', 'U') IS NULL
CREATE TABLE "MySchema"."Location" (
"Id" SMALLINT IDENTITY NOT NULL CONSTRAINT "PK_MySchema_Location" PRIMARY KEY,
"Region" TINYINT NOT NULL CONSTRAINT "FK_MySchema_Location_Region" FOREIGN KEY REFERENCES "MySchema"."Region" ("Id"),
"Name" VARCHAR(128) NOT NULL,
CONSTRAINT "UK_MySchema_Location" UNIQUE ("Region", "Name")
);
GO
IF OBJECT_ID('MySchema.Point', 'U') IS NULL
CREATE TABLE "MySchema"."Point" (
"ObjectId" BIGINT NOT NULL CONSTRAINT "PK_MySchema_Point" PRIMARY KEY,
"Name" VARCHAR(64) NOT NULL,
"LocationId" SMALLINT NULL CONSTRAINT "FK_MySchema_Point_Location" FOREIGN KEY REFERENCES "MySchema"."Location"("Id"),
"Region" TINYINT NOT NULL CONSTRAINT "FK_MySchema_Point_Region" FOREIGN KEY REFERENCES "MySchema"."Region" ("Id"),
CONSTRAINT "UK_MySchema_Point" UNIQUE ("Name", "Region", "LocationId")
);
GO
-- CONTAINS HISTORIC Point DATA
IF OBJECT_ID('MySchema.PointHistory', 'U') IS NULL
CREATE TABLE "MySchema"."PointHistory" (
"Id" BIGINT IDENTITY NOT NULL CONSTRAINT "PK_MySchema_PointHistory" PRIMARY KEY,
"ObjectId" BIGINT NOT NULL,
"Name" VARCHAR(64) NOT NULL,
"LocationId" SMALLINT NULL,
"Region" TINYINT NOT NULL
);
GO
CREATE TYPE "MySchema"."PointTable" AS TABLE (
"ObjectId" BIGINT NOT NULL PRIMARY KEY,
"PointName" VARCHAR(64) NOT NULL,
"Location" VARCHAR(16) NULL,
"Region" VARCHAR(8) NOT NULL,
UNIQUE ("PointName", "Region", "Location")
);
GO
DECLARE @p1 "MySchema"."PointTable";
insert into @p1 values(10001769996,N'ABCDEFGH',N'N/A',N'E')
MERGE "MySchema"."Point" AS t
USING (
SELECT "ObjectId", "PointName", z."Id" AS "LocationId", i."Id" AS "Region"
FROM @p1 AS d
JOIN "MySchema"."Region" AS i ON i."Name" = d."Region"
LEFT JOIN "MySchema"."Location" AS z ON z."Name" = d."Location" AND z."Region" = i."Id"
) AS s
ON s."ObjectId" = t."ObjectId"
WHEN NOT MATCHED BY TARGET
THEN INSERT ("ObjectId", "Name", "LocationId", "Region") VALUES (s."ObjectId", s."PointName", s."LocationId", s."Region")
WHEN MATCHED
THEN UPDATE
SET "Name" = s."PointName"
, "LocationId" = s."LocationId"
, "Region" = s."Region"
OUTPUT $action, inserted.*, deleted.*;
यदि मैं OUTPUT
खंड हटाता हूं तो त्रुटि नहीं होती है। इसके अलावा, यदि मैं deleted
संदर्भ हटाता हूं तो त्रुटि नहीं होती है। इसलिए मैंने OUTPUT
उस स्थिति के लिए MSDN दस्तावेजों को देखा, जो इस प्रकार है:
DELETED का उपयोग INSERT स्टेटमेंट में OUTPUT क्लॉज के साथ नहीं किया जा सकता है।
जो मेरे लिए समझ में आता है, हालाँकि इसका पूरा बिंदु MERGE
यह है कि आप पहले से नहीं जानते होंगे।
इसके अतिरिक्त, नीचे दी गई स्क्रिप्ट पूरी तरह से ठीक काम करती है चाहे जो भी कार्रवाई की जाए:
USE tempdb;
GO
CREATE TABLE dbo.Target(EmployeeID int, EmployeeName varchar(10),
CONSTRAINT Target_PK PRIMARY KEY(EmployeeID));
CREATE TABLE dbo.Source(EmployeeID int, EmployeeName varchar(10),
CONSTRAINT Source_PK PRIMARY KEY(EmployeeID));
GO
INSERT dbo.Target(EmployeeID, EmployeeName) VALUES(100, 'Mary');
INSERT dbo.Target(EmployeeID, EmployeeName) VALUES(101, 'Sara');
INSERT dbo.Target(EmployeeID, EmployeeName) VALUES(102, 'Stefano');
GO
INSERT dbo.Source(EmployeeID, EmployeeName) Values(103, 'Bob');
INSERT dbo.Source(EmployeeID, EmployeeName) Values(104, 'Steve');
GO
-- MERGE statement with the join conditions specified correctly.
USE tempdb;
GO
BEGIN TRAN;
MERGE Target AS T
USING Source AS S
ON (T.EmployeeID = S.EmployeeID)
WHEN NOT MATCHED BY TARGET AND S.EmployeeName LIKE 'S%'
THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName)
WHEN MATCHED
THEN UPDATE SET T.EmployeeName = S.EmployeeName
WHEN NOT MATCHED BY SOURCE AND T.EmployeeName LIKE 'S%'
THEN DELETE
OUTPUT $action, inserted.*, deleted.*;
ROLLBACK TRAN;
GO
इसके अलावा, मेरे पास अन्य प्रश्न हैं जो OUTPUT
उसी फैशन का उपयोग करते हैं जो एक त्रुटि फेंक रहा है और वे पूरी तरह से ठीक काम करते हैं - उनके बीच एकमात्र अंतर तालिकाओं है जो इसमें भाग लेते हैं MERGE
।
यह हमारे लिए उत्पादन में बड़ी समस्या पैदा कर रहा है। मैंने इस त्रुटि को SQL2014 और SQL2016 में VM और Physical दोनों पर 128GB RAM, 12 x 2.2GHZ कोर, विंडोज सर्वर 2012 R2 के साथ पुन: प्रस्तुत किया है।
क्वेरी से उत्पन्न अनुमानित निष्पादन योजना यहां पाई जा सकती है:
deleted.ObjectId
कि समस्या पैदा कर रहा है। OUTPUT $action, inserted.*, deleted.Name, deleted.LocationId, deleted.Region
ठीक काम करता है।
MySchema.PointTable
प्रकार का उपयोग न करके समस्या से बच सकते हैं , और केवल अंदर एक नग्न VALUES()
खंड, या # तालिका, या तालिका चर का उपयोग कर सकते हैं USING
। योगदान करने वाले कारकों को अलग करने में मदद मिल सकती है।
MERGE
पासHOLDLOCK
एक के लिए नहीं है , इसलिए यह दौड़ की स्थिति से प्रतिरक्षा नहीं है, और यहां तक कि विचार करने के लिए अभी भी अन्य कीड़े हैं या रिपोर्ट - - आप को हल करने के बाद। जो कुछ भी इस मुद्दे खड़ी कर रहा है)