83

これを検索しましたが、表示されたスレッドには、質問を理解していない人からの回答が多い傾向がありました。

次の構文を取ります。

SET IDENTITY_INSERT Table1 ON

このようなことをどのように行いますか:

GET IDENTITY_INSERT Table1

ただし、データベース内のデータや、この情報を取得するための設定には何もしたくありません。ありがとう!

4

8 に答える 8

39

はセッションセンシティブであるため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
于 2012-05-17T14:55:43.000 に答える
22

要約すれば:

  • ネイサンのソリューションは最速です:

    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';

于 2013-11-22T10:16:03.140 に答える
9

以下のコードを使用して、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 
于 2017-12-07T17:51:37.210 に答える
6

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
于 2014-06-03T18:07:32.840 に答える
1

とても良い質問です。同じ問題があります。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

于 2013-11-11T14:31:34.440 に答える
0

セッション変数について知りたい場合...良い質問ですが、この情報がどこで役立つかわかりません。挿入に対する通常のテーブル応答をチェックする通常の実行では、これは機能するはずです。

-特定のテーブルに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

楽しむ!

于 2012-09-11T20:04:49.287 に答える
0

これが私の解決策です。@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
于 2019-10-29T15:27:48.837 に答える
-1

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
于 2013-02-04T22:19:37.850 に答える