1

毎週、クライアントから、主キーのない非常に大きなテーブルが含まれるデータベースが送られてきます。その中に一意の ID を持つ列は null 可能です。

したがってALTER TABLE、主キーとして必要な列を NOT NULL に設定するために実行します。

ALTER TABLE Live1.dbo.Orders 
    ALTER COLUMN OrderID varchar(10) NOT NULL;

それから約 45 分後に完了し、主キーを追加します。

ALTER TABLE Live1.dbo.Orders 
    ADD CONSTRAINT PK_OrdersOrderID PRIMARY KEY CLUSTERED (OrderID)

これまでのところ、すべて順調で素晴らしいです。

それまでは、この長くて退屈な操作を自動化しようとします。

エージェント ジョブの一部として、クライアントのデータベースの復元が完了するとすぐに実行される非常に単純なストアド プロシージャを作成しました。

CREATE PROCEDURE dbo.AddPKey
AS
BEGIN
    SET NOCOUNT ON;

    ALTER TABLE Live1.dbo.Orders ALTER COLUMN OrderID varchar(10) NOT NULL;
    ALTER TABLE Live1.dbo.Orders ADD CONSTRAINT PK_OrdersOrderID PRIMARY KEY CLUSTERED (OrderID)
END
GO

これは 1 秒後に失敗し、次のエラー メッセージが表示されます。

テーブル 'Orders' の null 許容列に PRIMARY KEY 制約を定義できません。[SQLSTATE 42000] (エラー 8111) 制約またはインデックスを作成できませんでした。以前のエラーを参照してください。[SQLSTATE 42000] (エラー 1750)。ステップは失敗しました。

ALTER COLUMNそのため、前のステップが完了する前に主キー制約を設定しようとしています。主キー制約の追加を試みるまでに少なくとも 45 分はかかるはずですが、すぐに追加しようとします。手動で実行するとALTER COLUMN、問題なく動作します。

何を与える?何十ものストアド プロシージャを作成しましたが、どれもそのように動作しませんか?

強制的に待機させるにはどうすればよいですか? それが行末のセミコロンがしたことだと思いましALTER COLUMNたか?

アップデート:

ここで実際に何が起こっているかについての洞察に満ちた回答と明確化について、πに感謝します。最終的なストアド プロシージャは次のようになります。

DECLARE @DynamicSQL nvarchar(4000)
 ALTER TABLE Live1.dbo.Orders ALTER COLUMN OrderID varchar(10) NOT NULL;
SET @DynamicSQL = 'ALTER TABLE Live1.dbo.Orders
                     ADD CONSTRAINT PK_OrdersOrderID PRIMARY KEY CLUSTERED (OrderID);'
EXEC Live1.sys.sp_executesql @DynamicSQL

エラーなしで動作します:)

4

1 に答える 1

1

これは、ステートメントの解析時に、SQL Server が 2 番目のステートメントを解析するときに、列がまだ NULL 可能であるためです。

2 つのオプション:

  • を使用して、2 番目のステートメントを動的 SQL クエリとして実行しますsp_executesql。これにより、別のコンテキストが作成され、そのクエリが解析されると、最初のコンテキストが既に実行されています。
  • 主キーを追加するだけのストアド プロシージャを作成します。直接の変更/追加制約ステートメントの代わりにそれを実行します。

PS: セミコロンは、言語レベルでステートメントを区切る (必要に応じて終了する) 役割を果たします。ランタイム機能はありません。

于 2020-02-23T08:15:49.323 に答える