これは CLR UDT を作成して、データベース間でテーブル型を共有できるようにすることはできますか?
基本的に、ユーザー定義のテーブル タイプはデータベース間で共有できません。 CLR ベースの UDT はできる データベース間で共有できますが、同じアセンブリが両方のデータベースに読み込まれているなど、特定の条件が満たされている場合に限ります (詳細は上記の重複した質問にあります)。
この特定の状況では、DB1
から情報を渡す方法があります。 DB2
へ ですが、エレガントなソリューションではありません。テーブル タイプを使用するには、現在のデータベース コンテキストがテーブル タイプが存在するデータベースである必要があります。これは USE
を介して行われます ただし、ストアド プロシージャ内で実行する必要がある場合は、動的 SQL でのみ実行できます。
USE [DB1];GOCREATE PROCEDURE [dbo].[selectData] @psCustomList CustomList READONLYASBEGIN -- 動的 SQL CREATE TABLE #TempCustomList ( [ID] [INT], [表示] [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
の使用 単に UDTT を TVP として渡すことによってローカル一時テーブルを回避しようとしているか、単にパラメーター化されたクエリを実行する手段として、実際には機能しません (確かに機能するように見えますが)。つまり、次のとおりです:USE [DB1];GOCREATE PROCEDURE dbo.CrossDatabaseTableTypeA( @TheUDTT dbo.TestTable1 READONLY)ASSET 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;GODECLARE @tmp dbo.TestTable1;INSERT INTO @tmp ([Col1]) 値 (1), (3);SELECT * FROM @tmp;EXEC dbo.CrossDatabaseTableTypeA @TheUDTT =@tmp;
プレ>
DB2
が正しく表示されていても、「@TableTypeDB2 has an invalid datatype」で失敗します。 「現在の」データベースです。sp_executesql
の方法と関係があります エラーが@TableTypeDB2
を参照したため、変数のデータ型を決定します 入力パラメーターとしてではなくローカルに作成されますが、「変数 # 2」として。実際、
sp_executesql
単一の変数が宣言されている場合はエラーになります (sp_executesql
へのパラメーター リスト入力パラメーターを介して) )、使用されるどころか、参照されていない場合でも。つまり、次のコードでは、すぐ上のクエリで発生した UDTT の定義が見つからないという同じエラーが発生します。USE [DB1];GOCREATE PROCEDURE dbo.CrossDatabaseTableTypeCASSET NOCOUNT ON;EXEC sp_executesql N' USE [DB2]; SELECT DB_NAME() AS [CurrentDB]; DECLARE @TableTypeDB2 dbo.TestTable2; ', N'@SomeVar INT', @SomeVar =1;GO
プレ>(
sp_executesql
について言及してくれた @Mark Sowul に感謝します 変数を渡すときは機能しません)ただし、この問題は
sp_executesqlの実行データベースを変更することで回避できます (ただし、一時テーブルを回避するために TVP を渡そうとしない限り -- 上記の 2 つのクエリ)。コード> プロセスが、他の TVP が存在する DB に対してローカルになるようにします。
sp_executesql
の良いところ つまり、EXEC
とは異なります 、それはストアド プロシージャであり、システム ストアド プロシージャであるため、完全に修飾できます。この事実を利用すると、sp_executesql
が可能になります。 これは、USE [DB2];
の必要がないことも意味します。 動的 SQL 内のステートメント。次のコードは機能します:USE [DB1];GOCREATE PROCEDURE dbo.CrossDatabaseTableTypeD( @TheUDTT dbo.TestTable1 READONLY)ASSET NOCOUNT ON;-- 動的 SQLCREATE 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
プレ>