sql >> データベース >  >> RDS >> Sqlserver

SQL Server データベース間でユーザー定義のテーブル型を渡す

    これは 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 が存在する 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  


    1. postgresはゼロの繰り返しパターンを検出します

    2. Laravel 4:カスタムログインとパスワードの確認

    3. テーブルのフラッシュ-アクセスが拒否されました

    4. 列がINT(10)のときに10桁を挿入できないのはなぜですか