これを検索しましたが、表示されたスレッドには、質問を理解していない人からの回答が多い傾向がありました。
次の構文を取ります。
SET IDENTITY_INSERT Table1 ON
このようなことをどのように行いますか:
GET IDENTITY_INSERT Table1
ただし、データベース内のデータや、この情報を取得するための設定には何もしたくありません。ありがとう!
これを検索しましたが、表示されたスレッドには、質問を理解していない人からの回答が多い傾向がありました。
次の構文を取ります。
SET IDENTITY_INSERT Table1 ON
このようなことをどのように行いますか:
GET IDENTITY_INSERT Table1
ただし、データベース内のデータや、この情報を取得するための設定には何もしたくありません。ありがとう!
はセッションセンシティブであるためSET IDENTITY_INSERT
、どこかに保存せずにバッファレベルで管理されます。IDENTITY_INSERT
これは、現在のセッションではこのキーワードを使用しないため、ステータスを確認する必要がないことを意味します。
申し訳ありませんが、これについては助けになりません。
でも素晴らしい質問です:)
出典:こちら
更新 これを行う方法はいくつかありますが、私がリンクしたサイトIMOにも見られますが、これは非常に手間がかかりすぎて役に立ちません。
if
(select max(id) from MyTable) < (select max(id) from inserted)
--Then you may be inserting a record normally
BEGIN
set @I = 1 --SQL wants something to happen in the "IF" side of an IF/ELSE
END
ELSE --You definitely have IDENTITY_INSERT on. Done as ELSE instead of the other way around so that if there is no inserted table, it will run anyway
BEGIN
.... Code that shouldn't run with IDENTITY_INSERT on
END
要約すれば:
ネイサンのソリューションは最速です:
SELECT OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity');
APIラッパーを使用する場合、チェック全体を行のチェックだけに減らすことができます。たとえば、C#のSqlDataReaders
プロパティHasRows
と次のようなクエリ構造を使用する場合:
SELECT CASE OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity')
WHEN 1 THEN '1' ELSE NULL END
Ricardoのソリューションでは柔軟性が向上しますが、列のID名が必要です
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('MyTable', 'U')
AND name = 'MyTableIdentityColumnName';
try
/を使用するBogdanBodanovソリューションcatch
も同様に機能しますが、追加のチェックにより、例外処理を次の場合に限定する必要があります。 IDENTITY_INSERT is already ON for table 'MyTable'. Cannot perform SET operation for table 'MyTable';
以下のコードを使用して、identity_insertがオンになっているかどうか、オンになっている場合はどのテーブルにあるかを確認できます。
declare @tableWithIdentity varchar(max) = '';
SET IDENTITY_INSERT ExampleTable ON
begin try
create table #identityCheck (id int identity(1,1))
SET IDENTITY_INSERT #identityCheck ON
drop table #identityCheck
end try
begin catch
declare @msg varchar(max) = error_message()
set @tableWithIdentity= @msg;
set @tableWithIdentity =
SUBSTRING(@tableWithIdentity,charindex('''',@tableWithIdentity,1)+1, 10000)
set @tableWithIdentity = SUBSTRING(@tableWithIdentity,1, charindex('''',@tableWithIdentity,1)-1)
print @msg;
drop table #identityCheck
end catch
if @tableWithIdentity<>''
begin
print ('Name of table with Identity_Insert set to ON: ' + @tableWithIdentity)
end
else
begin
print 'No table currently has Identity Insert Set to ON'
end
IDENTITY_INSERTをオンに設定するときにエラーが発生しないように、他のテーブルのIDENTITY_INSERTをオフにしようとしている場合は、次の方法でも機能する可能性があります。他の人がこのスレッドで言ったように、IDENTITY_INSERTは直接の可視性のないセッション設定です。ただし、IDENTITY_INSERTがオンであるかどうかに関係なく、IDを持つテーブルに対してSETIDENTITY_INSERTOFFがエラーにならないという興味深い発見をしました。そのため、データベース内のIDを持つすべてのテーブルに対してSET IDENTITY_INSERT...OFFを呼び出すことができることに気付きました。ブルートフォースソリューションのように感じますが、次の動的SQLブロックが非常にうまく機能していることがわかりました。
---- make sure IDENTITY_INSERT is OFF ----
DECLARE @cmd NVARCHAR(MAX)
SET @cmd = CAST((SELECT 'SET IDENTITY_INSERT ' +
QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + '.' +
QUOTENAME(t.name) + ' OFF' + CHAR(10)
FROM sys.columns c
JOIN sys.tables t ON t.object_id = c.object_id
WHERE c.is_identity = 1
ORDER BY 1 FOR XML PATH('')) AS NVARCHAR(MAX))
EXEC sp_executesql @cmd
とても良い質問です。同じ問題があります。TRY /CATCHを使用してIDENTITY_INSERTをリセットしてみてください。たとえば、ジョブを作成しましたが、ジョブが終了してIDENTITY_INSERTがOFFに設定されているかどうかがわかりません。
試さない理由:
BEGIN TRY
...
END TRY
BEGIN CATCH
SET IDENTITY_INSERT table OFF;
END CATCH;
また、これが正しく機能しているかどうかはわかりませんが、追加しただけでSET IDENTITY_INSERT ... OFF
はエラーが返されなかったことがわかります。だから、最後に念のために設定することができますSET IDENTITY_INSERT ... OFF
。
セッション変数について知りたい場合...良い質問ですが、この情報がどこで役立つかわかりません。挿入に対する通常のテーブル応答をチェックする通常の実行では、これは機能するはずです。
-特定のテーブルにIDが挿入されているかどうかだけを知りたい場合は、次のようにします。
select is_identity
from sys.columns
where object_id = OBJECT_ID('MyTable', 'U') and name = 'column_Name'
-または...結果に応じて何かを実行する場合は、これを使用します。
if exists (select *
from sys.columns
where object_id = OBJECT_ID('MyTable', 'U') and is_identity = 1)
... your code considering identity insert
else
... code that should not run with identity insert
楽しむ!
これが私の解決策です。@jmorenoの答えと非常によく似ています。
あなたはそれをこのように呼ぶでしょう
DECLARE @IdentityInsert VARCHAR(20)
EXEC dbo.GetIdentityInsert 'YourDb', 'YourSchema', 'YourTable', @IdentityInsert OUT
SELECT @IdentityInsert
これにより、列名IDENTITY_INSERTの1行のレコードセットが返されます。これは、ON、OFF、またはNO_IDENTITYのいずれかになります(指定されたテーブルにID列がない場合)。また、出力パラメーター@IdentityInsertを設定します。したがって、コードを好みの方法に調整できます。
これをユーザー定義関数に組み込むのは良いことですが、残念ながら、ユーザー定義関数では使用できないTRY..CATCHブロックを回避する方法を見つけることができませんでした。
-- ================================================================================
-- Check whether the table specified has its IDENTITY_INSERT set to ON or OFF.
-- If the table does not have an identity column, NO_IDENTITY is returned.
-- Tested on SQL 2008.
-- ================================================================================
CREATE PROCEDURE dbo.GetIdentityInsert
@dbname sysname
, @schemaname sysname
, @table sysname
, @IdentityInsert VARCHAR(20) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE @OtherTable nvarchar(max)
DECLARE @DbSchemaTable nvarchar(max)
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
DECLARE @ErrorNumber INT;
DECLARE @object_id INT;
SET @DbSchemaTable = @dbname + '.' + @schemaname + '.' + @table
SET @object_id = OBJECT_ID(@DbSchemaTable)
IF @object_id IS NULL
BEGIN
RAISERROR('table %s doesn''t exist', 16, 1, @DbSchemaTable)
RETURN
END
BEGIN TRY
SET @object_id = OBJECT_ID(@DbSchemaTable)
IF OBJECTPROPERTY(@object_id,'TableHasIdentity') = 0
BEGIN
SET @IdentityInsert = 'NO_IDENTITY'
END
ELSE
BEGIN
-- Attempt to set IDENTITY_INSERT on a temp table. This will fail if any other table
-- has IDENTITY_INSERT set to ON, and we'll process that in the CATCH
CREATE TABLE #GetIdentityInsert(ID INT IDENTITY)
SET IDENTITY_INSERT #GetIdentityInsert ON
SET IDENTITY_INSERT #GetIdentityInsert OFF
DROP TABLE #GetIdentityInsert
-- It didn't fail, so IDENTITY_INSERT on @table must set to OFF
SET @IdentityInsert = 'OFF'
END
END TRY
BEGIN CATCH
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorNumber = ERROR_NUMBER();
IF @ErrorNumber = 8107 --IDENTITY_INSERT is already set on a table
BEGIN
SET @OtherTable = SUBSTRING(@ErrorMessage, CHARINDEX(char(39), @ErrorMessage)+1, 2000)
SET @OtherTable = SUBSTRING(@OtherTable, 1, CHARINDEX(char(39), @OtherTable)-1)
IF @OtherTable = @DbSchemaTable
BEGIN
-- If the table name is the same, then IDENTITY_INSERT on @table must be ON
SET @IdentityInsert = 'ON'
END
ELSE
BEGIN
-- If the table name is different, then IDENTITY_INSERT on @table must be OFF
SET @IdentityInsert = 'OFF'
END
END
ELSE
BEGIN
RAISERROR (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState);
--THROW Use this if SQL 2012 or higher
END
END CATCH
SELECT [IDENTITY_INSERT] = @IdentityInsert
END
GO
ObjectPropertyメソッドを使用して、テーブルにIDがあるかどうかを判別することもできます。
DECLARE @MyTableName nvarchar(200)
SET @MyTableName = 'TestTable'
SELECT CASE OBJECTPROPERTY(OBJECT_ID(@MyTableName), 'TableHasIdentity')
WHEN 1 THEN 'has identity'
ELSE 'no identity columns'
END as HasIdentity