यह क्या आप एक सीएलआर यूडीटी बना सकते हैं ताकि सभी डेटाबेस में साझा टेबल प्रकार की अनुमति दी जा सके?
अनिवार्य रूप से, उपयोगकर्ता-परिभाषित तालिका प्रकारों को डेटाबेस में साझा नहीं किया जा सकता है। सीएलआर-आधारित यूडीटी कर सकते हैं डेटाबेस में साझा किया जा सकता है, लेकिन केवल अगर कुछ शर्तों को पूरा किया गया है, जैसे कि एक ही असेंबली को दोनों डेटाबेस में लोड किया जा रहा है, और कुछ अन्य चीजें (विवरण ऊपर उल्लिखित डुप्लिकेट प्रश्न में हैं)।
इस विशेष स्थिति के लिए, DB1
. से जानकारी पास करने का एक तरीका है करने के लिए DB2
, हालांकि यह एक सुरुचिपूर्ण समाधान नहीं है। तालिका प्रकार का उपयोग करने के लिए, आपके वर्तमान डेटाबेस संदर्भ को वह डेटाबेस होना चाहिए जिसमें तालिका प्रकार मौजूद है। यह USE
. के माध्यम से किया जाता है कथन, लेकिन यह केवल गतिशील SQL में किया जा सकता है यदि किसी संग्रहीत प्रक्रिया के भीतर करने की आवश्यकता हो।
USE [DB1];
GO
CREATE PROCEDURE [dbo].[selectData]
@psCustomList CustomList READONLY
AS
BEGIN
-- create a temp table as it can be referenced in dynamic SQL
CREATE TABLE #TempCustomList
(
[ID] [INT],
[Display] [NVARCHAR] (100)
);
INSERT INTO #TempCustomList (ID, Display)
SELECT ID, Display FROM @psCustomList;
EXEC('
USE [DB2];
DECLARE @VarCustomList CustomList;
INSERT INTO @VarCustomList (ID, Display)
SELECT ID, Display FROM #TempCustomList;
EXEC dbo.selectMoreData @VarCustomList;
');
END
अपडेट करें
sp_executesql
का उपयोग करना , या तो यूडीटीटी में एक टीवीपी के रूप में, या केवल एक पैरामीटरयुक्त क्वेरी करने के साधन के रूप में पास करके स्थानीय अस्थायी तालिका से बचने के प्रयास में, वास्तव में काम नहीं करता है (हालांकि यह निश्चित रूप से ऐसा दिखता है)। अर्थ, निम्नलिखित:
USE [DB1];
GO
CREATE PROCEDURE dbo.CrossDatabaseTableTypeA
(
@TheUDTT dbo.TestTable1 READONLY
)
AS
SET NOCOUNT ON;
EXEC sp_executesql N'
USE [DB2];
SELECT DB_NAME() AS [CurrentDB];
DECLARE @TableTypeDB2 dbo.TestTable2;
INSERT INTO @TableTypeDB2 ([Col1])
SELECT tmp.[Col1]
FROM @TableTypeDB1 tmp;
--EXEC dbo.CrossDatabaseTableTypeB @TableTypeDB2;
',
N'@TableTypeDB1 dbo.TestTable1 READONLY',
@TableTypeDB1 = @TheUDTT;
GO
DECLARE @tmp dbo.TestTable1;
INSERT INTO @tmp ([Col1]) VALUES (1), (3);
SELECT * FROM @tmp;
EXEC dbo.CrossDatabaseTableTypeA @TheUDTT = @tmp;
"@TableTypeDB2 में एक अमान्य डेटाटाइप है" पर विफल हो जाएगा, भले ही यह सही ढंग से प्रदर्शित करता है कि DB2
"वर्तमान" डेटाबेस है। इसका कुछ लेना-देना है कि कैसे sp_executesql
@TableTypeDB2
. को संदर्भित त्रुटि के बाद से चर डेटाटाइप निर्धारित करता है "चर # 2" के रूप में, भले ही इसे स्थानीय रूप से बनाया गया हो और इनपुट पैरामीटर के रूप में नहीं।
वास्तव में, sp_executesql
यदि एकल चर घोषित किया गया है तो त्रुटि होगी (पैरामीटर सूची इनपुट पैरामीटर के माध्यम से sp_executesql
), भले ही इसे कभी संदर्भित न किया गया हो, अकेले उपयोग करें। मतलब, निम्न कोड UDTT के लिए परिभाषा खोजने में सक्षम नहीं होने की उसी त्रुटि में चलेगा जो तुरंत ऊपर क्वेरी के साथ होता है:
USE [DB1];
GO
CREATE PROCEDURE dbo.CrossDatabaseTableTypeC
AS
SET NOCOUNT ON;
EXEC sp_executesql N'
USE [DB2];
SELECT DB_NAME() AS [CurrentDB];
DECLARE @TableTypeDB2 dbo.TestTable2;
',
N'@SomeVar INT',
@SomeVar = 1;
GO
(उल्लेख करने के लिए @Mark Sowul का धन्यवाद sp_executesql
चर में गुजरते समय काम नहीं करता)
हालांकि, sp_executesql
के निष्पादन डेटाबेस को बदलकर इस समस्या को हल किया जा सकता है (ठीक है, जब तक आप अस्थायी तालिका - 2 प्रश्नों से बचने के लिए टीवीपी में पास करने की कोशिश नहीं कर रहे हैं)। कोड> ताकि प्रक्रिया डीबी के लिए स्थानीय हो जिसमें अन्य टीवीपी मौजूद है। sp_executesql
के बारे में एक अच्छी बात क्या वह EXEC
. के विपरीत है , यह एक संग्रहीत प्रक्रिया है, और उस पर एक सिस्टम संग्रहीत प्रक्रिया है, इसलिए इसे पूरी तरह से योग्य बनाया जा सकता है। इस तथ्य का उपयोग करने की अनुमति देता है sp_executesql
काम करने के लिए, जिसका अर्थ यह भी है कि USE [DB2];
. की कोई आवश्यकता नहीं है डायनामिक एसक्यूएल के भीतर बयान। निम्नलिखित कोड काम करता है:
USE [DB1];
GO
CREATE PROCEDURE dbo.CrossDatabaseTableTypeD
(
@TheUDTT dbo.TestTable1 READONLY
)
AS
SET NOCOUNT ON;
-- create a temp table as it can be referenced in dynamic SQL
CREATE TABLE #TempList
(
[ID] [INT]
);
INSERT INTO #TempList ([ID])
SELECT [Col1] FROM @TheUDTT;
EXEC [DB2].[dbo].sp_executesql N'
SELECT DB_NAME() AS [CurrentDB];
DECLARE @TableTypeDB2 dbo.TestTable2;
INSERT INTO @TableTypeDB2 ([Col1])
SELECT tmp.[ID]
FROM #TempList tmp;
EXEC dbo.CrossDatabaseTableTypeB @TableTypeDB2;
',
N'@SomeVariable INT',
@SomeVariable = 1111;
GO