IDを既存の列に追加する


445

テーブルの主キーをID列に変更する必要がありますが、テーブルには既に多数の行があります。

IDをクリーンアップして、1から順にシーケンシャルになるようにするスクリプトがあります。テストデータベースで正常に動作します。

IDプロパティを持つように列を変更するSQLコマンドは何ですか?

回答:


482

IDの既存の列を変更することはできません。

2つのオプションがあります。

  1. IDを使用して新しいテーブルを作成し、既存のテーブルを削除します

  2. IDを使用して新しい列を作成し、既存の列をドロップします

アプローチ1.(新しいテーブル)ここでは、新しく作成されたID列に既存のデータ値を保持できます。

CREATE TABLE dbo.Tmp_Names
    (
      Id int NOT NULL
             IDENTITY(1, 1),
      Name varchar(50) NULL
    )
ON  [PRIMARY]
go

SET IDENTITY_INSERT dbo.Tmp_Names ON
go

IF EXISTS ( SELECT  *
            FROM    dbo.Names ) 
    INSERT  INTO dbo.Tmp_Names ( Id, Name )
            SELECT  Id,
                    Name
            FROM    dbo.Names TABLOCKX
go

SET IDENTITY_INSERT dbo.Tmp_Names OFF
go

DROP TABLE dbo.Names
go

Exec sp_rename 'Tmp_Names', 'Names'

アプローチ2(新しい列)新しく作成されたID列に既存のデータ値を保持することはできません。ID列は番号のシーケンスを保持します。

Alter Table Names
Add Id_new Int Identity(1, 1)
Go

Alter Table Names Drop Column ID
Go

Exec sp_rename 'Names.Id_new', 'ID', 'Column'

詳細については、次のMicrosoft SQL Serverフォーラムの投稿を参照してください。

列をidentity(1,1)に変更する方法


49
テーブルデータが小さい場合、このオプションはうまくいきます。テーブルが大きい場合は、別のオプションとして、ALTER TABLE ... SWITCHを使用して、テーブルスキーマをIDENTITY列を持つがそれ以外は同一のスキーマを持つ別のバージョンに置き換えます。ALTER TABLE .... SWITCHアプローチの利点は、テーブルデータをコピーまたは変更する必要がないため、すばやく完了する(10億行のテーブルでは5秒未満)ことです。ただし、注意事項と制限事項があります。詳細については、以下の私の回答を参照してください。
ジャスティングラント

7
@Justin Grat:非常に興味深い代替案であり、私が考慮していなかった代替案です!これが機能する理由は、IDENTITYがデータ型ではなく列のプロパティであるため、SWITCHメソッドは2つのテーブル(古いものと新しいもの)の間のスキーマを、IDENTITYの違いに関係なく識別可能であることを検証します。共有してくれてありがとう!
John Sansom、

データが少ない場合は、SSMSからスクリプトを生成することで「テーブルの作成」を実現できます。テーブルを右クリック> [テーブルの名前を変更]> [TABLEの作成]>(新しいクエリエディター?)。次に、それをドロップし、そのスクリプト内にIDENTITY(1, 1)、主キー列を持つ部品を追加できます
goamn

SSMSを使用してこれを強制することもできます。[ツール]> [オプション]> [デザイナー]に移動し、[テーブルの再作成が必要な変更を保存できないようにする]をオフにします。ところで、これはかなり大きなテーブルには推奨されません。
Zafar

PostgreSQL では、次のコマンドを使用して、既存の整数列にIDを追加できます。
アンドリューマッキー

209

SQL 2005以降では、テーブルのデータページを変更せずにこの問題を解決するトリックがあります。これは、すべてのデータページに触れるのに数分または数時間かかる可能性がある大きなテーブルでは重要です。このトリックは、ID列が主キーである場合、クラスター化または非クラスター化インデックスの一部である場合、またはより単純な「列の追加/削除/名前変更」ソリューションを実行する可能性があるその他の問題でも機能します。

ここに秘訣があります:SQL ServerのALTER TABLE ... SWITCHを使用できますステートメントをして、データを変更せずにテーブルのスキーマを変更できます。つまり、テーブルをIDENTITYに置き換えることができますが、IDENTITY列はありません。同じトリックがIDENTITYを既存の列に追加するために機能します。

通常、ALTER TABLE ... SWITCHは、パーティションテーブルの完全なパーティションを新しい空のパーティションで効率的に置き換えるために使用されます。ただし、パーティション化されていないテーブルでも使用できます。

このトリックを使用して、5秒未満で、25億行のテーブルの列をIDENTITYから非IDENTITYに変換しました(非IDENTITYでクエリプランがより効果的に機能する数時間のクエリを実行するため)列)、次にIDENTITY設定を5秒未満で復元しました。

これがどのように機能するかのサンプルコードです。

 CREATE TABLE Test
 (
   id int identity(1,1),
   somecolumn varchar(10)
 );

 INSERT INTO Test VALUES ('Hello');
 INSERT INTO Test VALUES ('World');

 -- copy the table. use same schema, but no identity
 CREATE TABLE Test2
 (
   id int NOT NULL,
   somecolumn varchar(10)
 );

 ALTER TABLE Test SWITCH TO Test2;

 -- drop the original (now empty) table
 DROP TABLE Test;

 -- rename new table to old table's name
 EXEC sp_rename 'Test2','Test';

 -- update the identity seed
 DBCC CHECKIDENT('Test');

 -- see same records
 SELECT * FROM Test; 

これは他の回答の解決策よりも明らかに複雑ですが、テーブルが大きい場合、これは実際の命の恩人になります。いくつかの注意点があります:

  • 私の知る限り、IDは、このメソッドでテーブルの列について変更できる唯一のものです。列の追加/削除、null可能性の変更などは許可されていません。
  • 切り替えを行う前に元のキーをドロップし、後で復元する必要があります。
  • WITH SCHEMABINDING関数、ビューなども同様です。
  • 新しいテーブルのインデックスは完全に一致する必要があります(同じ列、同じ順序など)
  • 古いテーブルと新しいテーブルは同じファイルグループ上にある必要があります。
  • SQL Server 2005以降でのみ機能します
  • 私は以前、このトリックはSQL ServerのEnterpriseまたはDeveloperエディションでのみ機能すると信じていました(パーティションはEnterpriseおよびDeveloperバージョンでのみサポートされているため)。これは、EnterpriseまたはDeveloperへの制限がALTER TABLE ... SWITCHに適用されないことを意味すると思います。

上記の要件について詳しく説明したTechNetの良い記事があります。

更新-Eric Wuは、このソリューションに関する重要な情報を追加するコメントを以下に示しました。ここにそれをコピーして、より注目されるようにします。

ここで、言及する価値のある別の警告があります。新しいテーブルは古いテーブルからデータを喜んで受け取り、すべての新しい行はIDパターンに従って挿入されますが、それらは1から始まり、上記の列が主キーである場合は壊れる可能性があります。DBCC CHECKIDENT('<newTableName>')切り替え直後に実行することを検討してください。詳細については、msdn.microsoft.com / en-us / library / ms176057.aspxを参照してください

テーブルが新しい行でアクティブに拡張されている場合(IDENTITYを追加してから新しい行を追加するまでのダウンタイムがほとんどない場合)DBCC CHECKIDENT、新しいテーブルスキーマのIDシード値を手動で設定する代わりに、テーブル内の最大の既存のIDよりも大きい(例:)とのIDENTITY (2435457, 1)両方をトランザクションに含めることができる場合があります(またはこれをテストしていません)。ただし、シード値を手動で設定する方が簡単で安全です。ALTER TABLE...SWITCHDBCC CHECKIDENT

明らかに、新しい行がテーブルに追加されていない場合(または、毎日のETLプロセスのように時々追加されるだけの場合)、この競合状態は発生しないので問題DBCC CHECKIDENTありません。


5
私の記憶が正しい場合、私はこの記事からアイデアを得ました: 。sqlservercentral.com articles T
Justin Grant

2
参考までに、これはSQL 2008 R2の標準バージョンでも機能するようです。おそらく、バックアップ圧縮をオンにする機能を有効にしたのと同じように、この機能を有効にしました。
Mason G. Zhwiti、2011年

3
@jbatista-OPの質問では、テーブルに主キーがすでにあり、適切な値を確実に確保できたが、IDENTITY列に変更したかっただけです。上記の私の答えは、その狭いユースケースに焦点を当てています:実際にデータを変更せずにIDENTITYを列に追加する方法。上記で説明したアプローチは、大きなテーブルの場合、時間を大幅に節約できます。データを変更する必要がある場合は、他のソリューションを使用する必要があります。
ジャスティングラント

3
ここで、言及する価値のある別の警告があります。新しいテーブルは古いテーブルからデータを喜んで受け取り、すべての新しい行はIDパターンに従って挿入されますが、それらは1から始まり、上記の列が主キーである場合は壊れる可能性があります。DBCC CHECKIDENT('<newTableName>')切り替え直後に実行することを検討してください。詳細については、msdn.microsoft.com / en-us / library / ms176057.aspxを参照してください
Eric Wu

3
これは素晴らしい答えです!列のNULL可能性は同じでなければならないことにも注意してください。したがって、列のNULL可能性を変更する必要がある場合は、後の手順で変更する必要があります。PK制約についても同様です。また、現在の最大値と一致するようにテーブル作成のID値を変更します:IDENTITY(maxID + 1、1)
Philippe

71

列をIDENTITY列に変更することはできません。必要なのは、get-goからIDENTITYとして定義された新しい列を作成し、古い列を削除して、新しい列の名前を古い名前に変更することです。

ALTER TABLE (yourTable) ADD NewColumn INT IDENTITY(1,1)

ALTER TABLE (yourTable) DROP COLUMN OldColumnName

EXEC sp_rename 'yourTable.NewColumn', 'OldColumnName', 'COLUMN'

マーク


パラメータ\ @objnameがあいまいであるか、要求された\ @objtype(COLUMN)が間違っています。
ジェニー・オライリー2013年

1
@ JennyO'Reilly:別の質問に入れて、使用しいる完全なコマンドを見せてください
marc_s 2013年

2
失敗していたのはsp_renameプロシージャでした。エラーテキストを検索して、stackoverflowの解決策を見つけました。私のテーブルの名前には特別な文字は含まれていませんが、これは角括弧を使用した厳密な構文規則のようです。
ジェニー・オライリー

1
または、「ALTER TABLE(yourTable)DROP COLUMN OldColumnName」と「ALTER TABLE(yourTable)ADD OldColumnName INT IDENTITY(1,1)」のように、名前を変更する理由:p
RK Sharma

マルク、私は巨大なテーブル(約300mln行)でこの正確なコマンドを試しましたが、約10分後にプロセスを停止しました
ナオミ

14

ここで説明されているクールなソリューションがあります: SQLサーバー-列のIDプロパティの追加または削除

簡単に説明すると、SQL Managerでテーブルを手動で編集し、IDを切り替え、変更を保存せず、変更用に作成されるスクリプトを表示し、コピーして後で使用します。

変更するテーブルに関連するすべての外部キー、インデックスなどがスクリプトに含まれているため、時間を大幅に節約できます。これを手動で書く...神は禁じた。


これは私が使用したソリューションです-SSMSは変更を行うためにT-SQLを生成します...同じスキーマ設計の新しい一時テーブルを作成し、そこにすべての行をコピーし、origを削除して名前を変更することで。完全に実行するには少し時間がかかりますが、完全に機能しました。
mdelvecchio 2014

Pinal Daveが実際に生成したスクリプトを実行する必要があると言っているとは思いません。UIを介して変更を加えることで何ができるかを示すためだけです...
Zack

(テーブルの定義の変更に関する)SSMSのこのスクリプト機能は、パーティション化されたテーブルを文書化するときに実際に唯一正しい機能です。最も適切な場所「タスク」->「スクリプトテーブル」では、常にパーティション分割関数のスクリプトを作成することを忘れます!
Martijn van der Jagt

1
誰かに役立つかもしれません。変更後に変更スクリプトを取得します。SSMSのデザインモードでテーブルを右クリックし、[変更スクリプトの生成]オプションを選択して、スクリプトをローカルドライブに保存します
Vijai

11

IDENTITYの代わりにSEQUENCEの使用を検討してください。

SQL Server 2014(下位バージョンについてはわかりません)では、シーケンスを使用してこれを簡単に行うことができます。

CREATE SEQUENCE  sequence_name START WITH here_higher_number_than_max_existed_value_in_column INCREMENT BY 1;

ALTER TABLE table_name ADD CONSTRAINT constraint_name DEFAULT NEXT VALUE FOR sequence_name FOR column_name

ここから:列のデフォルト値としてのシーケンス


6

簡単な説明

sp_RENAMEを使用して既存の列の名前を変更する

EXEC sp_RENAME 'Table_Name.Existing_ColumnName'、 'New_ColumnName'、 'C​​OLUMN'

名前変更の例:

既存の列UserIDの名前がOldUserIDに変更されます

EXEC sp_RENAME 'AdminUsers.UserID' , 'OldUserID', 'COLUMN'

次に、alter queryを使用して新しい列を追加し、主キーとID値として設定します

ALTER TABLE TableName ADD Old_ColumnName INT NOT NULL PRIMARY KEY IDENTITY(1,1)

主キーの設定の例

新しく作成された列名はUserIDです

ALTER TABLE Users ADD UserID INT NOT NULL PRIMARY KEY IDENTITY(1,1)

次に、名前を変更した列をドロップします

ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName

名前を変更した列の削除の例

ALTER TABLE Users DROP COLUMN OldUserID

これで、テーブルの既存の列に主キーとIDを追加しました。


5

私はたまたまDBAなしでチームに参加したJava開発者であり、開発者としてDBA権限を取得できない人です。私は2つのデータベース間でスキーマ全体を移動するタスクがあったため、DBAがいない場合は、スクリプトを実行する必要があり、SQL Server 2008でGUIを使用できないため、管理者権限を持っていませんでした。

すべてが問題なく移動されましたが、新しいschema.tableでストアドプロシージャを実行すると、テーブルのIDフィールドが失われました。テーブルを作成したスクリプトを再確認したところ、そこにありましたが、スクリプトを実行したときにSQL Serverが取得しませんでした。後でDBAから、同じ問題が以前にも見られたと言われました。

いずれにしても、SQL Server 2008では、これらを解決して機能させるために私が取った手順です。そのため、誰かの助けになることを期待して、ここに投稿します。これは、別のテーブルへのFK依存関係があったために私がやったことで、これがさらに困難になりました。

このクエリを使用して、IDが実際に存在しないことを確認し、テーブルの依存関係を表示しました。

1.)テーブルの統計を見つける:

exec sp_help 'dbo.table_name_old';

2.)以前と同じ場所にあるPKフィールドにIDフィールドを追加することを除いて、同一の新しい新しいテーブルを作成します。

3.)IDを無効にしてデータを移動します。

SET IDENTITY_INSERT dbo.table_name ON 

4.)データを転送します。

INSERT INTO dbo.table_name_new
(
field1, field2, etc...
)
SELECT 
field1, field2, etc...
FROM 
dbo.table_name_old;

5.)データが存在することを確認します。

SELECT * FROM dbo.table_name_new

6.)IDを再度有効にします。

SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF

7.)これは、すべてのFK関係を取得して、元のテーブルが依存関係として参照しているテーブルを確認するために見つけた最良のスクリプトであり、多くの場合、キーパーです。

SELECT f.name AS ForeignKey,
   OBJECT_NAME(f.parent_object_id) AS TableName,
   COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
   OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
   COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
   ON f.OBJECT_ID = fc.constraint_object_id
   ORDER BY ReferenceTableName;

8.)この次のステップの前に、関係するすべてのテーブルのすべてのPKおよびFKスクリプトがあることを確認してください。

9.)各キーを右クリックし、SQL Server 2008を使用してこれをスクリプト化できます

10.)次の構文を使用して、依存関係テーブルからFKを削除します。

ALTER TABLE [dbo].[table_name] DROP CONSTRAINT [Name_of_FK]

11.)元のテーブルを削除します。

DROP TABLE dbo.table_name_old;

13.)次の手順は、SQL Server 2008で手順9で作成したスクリプトに依存しています。

-新しいテーブルにPKを追加します。

-FKを新しいテーブルに追加します。

--FKを依存関係テーブルに戻します。

14.)すべてが正しく、完全であることを確認します。GUIを使用してテーブルを確認しました。

15.)新しいテーブルの名前を元のテーブルの名前に変更します。

exec sp_RENAME '[Schema_Name.OldTableName]' , '[NewTableName]';

最後に、すべてがうまくいきました!


4

そのようにすることはできません。別の列を追加し、元の列をドロップして新しい列の名前を変更するか、新しいテーブルを作成するか、データをコピーして古いテーブルをドロップしてから、新しいテーブルの名前を古い名前に変更する必要がありますテーブル

SSMSを使用してデザイナでIDプロパティをONに設定すると、SQL Serverがバックグラウンドで実行します。したがって、[user]という名前のテーブルがある場合、UserIDとIDを作成すると、次のようになります。

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION

GO

GO
CREATE TABLE dbo.Tmp_User
    (
    UserID int NOT NULL IDENTITY (1, 1),
    LastName varchar(50) NOT NULL,
    FirstName varchar(50) NOT NULL,
    MiddleInitial char(1) NULL

    )  ON [PRIMARY]
GO

SET IDENTITY_INSERT dbo.Tmp_User ON
GO
IF EXISTS(SELECT * FROM dbo.[User])
 EXEC('INSERT INTO dbo.Tmp_User (UserID, LastName, FirstName, MiddleInitial)
    SELECT UserID, LastName, FirstName, MiddleInitialFROM dbo.[User] TABLOCKX')
GO
SET IDENTITY_INSERT dbo.Tmp_User OFF
GO

GO
DROP TABLE dbo.[User]
GO
EXECUTE sp_rename N'dbo.Tmp_User', N'User', 'OBJECT'
GO
ALTER TABLE dbo.[User] ADD CONSTRAINT
    PK_User PRIMARY KEY CLUSTERED 
    (
    UserID
    ) ON [PRIMARY]

GO
COMMIT

システムテーブルをハッキングしてビット単位の値を設定する方法はあると述べましたが、これはサポートされていないため、実行しません


4

私は、通常のケースでは理解されているように、私たちはしてテーブルを作成しているプライマリキー持っているアイデンティティプロパティ
だから、名前を変更または削除に関連付けられている列主キーの 制約は、制約ルールが列構造を検証するために行うことはできません。
:これは、我々は次のようにいくつかのステップを処理する必要が達成ット
たちは仮定しようテーブル名=「従業員」ColumnNameのを=「社員」

1.「従業員」テーブルに新しい列「EmployeeId_new」を追加
ALTER TABLE従業員がEmployeeId_new INT IDENTITYを(ADD 1,1)

  1. 次に、 'Employee'テーブルから列 'EmployeeId'を削除します
    ALTER TABLE Employee DROP COLUMN EmployeeId

  2. 主キー制約ルールが適用可能であり、列構造を検証しているため、これはエラーをスローします。
    * ### ' メッセージ5074、レベル16、状態1、行1オブジェクト[PK_dbo.Employee]はcolmn [EmployeeId]に依存しています。###

  3. したがって、まずテーブル 'Employee'から主キー制約を削除する必要があります。次に、列ALTER TABLE Employee DROP制約[PK_dbo.Employee]を削除できます

  4. これで、ALTER TABLE Employee DROP COLUMN EmployeeIdエラーが発生した前の手順で行ったように、「EmployeeId」列を「Employee」テーブルから削除できます。

  5. 列「EmployeeId」がテーブルから削除されたので、新しく追加された新しい列「EmployeeId_new」の名前を「EmployeeId」で変更し
    ますsp_rename 'Employee.EmployeeId'、 'EmployeeId_new'、 'C​​OLUMN'

  6. テーブルを以前と同じ形式に再配置するには、列 'EmployeeId'に主キー制約を追加する必要があります
    ALTER TABLE Employee追加制約[PK_dbo.Employee]主キー(EmployeeId)

8. これで、「EmployeeId」を持つテーブル「Employee」が、既存の主キー制約とともにIdentityルール用に変更されました。


3

設計上、既存の列のID機能をオンまたはオフにする簡単な方法はありません。これを行う唯一のクリーンな方法は、新しい列を作成してそれをID列にするか、新しいテーブルを作成してデータを移行することです。

SQL Server Management Studioを使用して列 "id"のID値を削除すると、新しい一時テーブルが作成され、データが一時テーブルに移動され、古いテーブルが削除され、新しいテーブルの名前が変更されます。

Management Studioを使用して変更を行い、デザイナーで右クリックして[変更スクリプトの生成]を選択します。

これは、SQLサーバーがバックグラウンドで実行していることです。


2

残念ながらありません。IDENTITYプロパティは、列ではなくテーブルに属しています。

簡単な方法はGUIでそれを行うことですが、これがオプションでない場合は、データをコピーし、列をドロップし、IDを使用して再度追加し、データを戻すという長い道のりをたどることができます。

ブローバイブローのアカウントについては、こちらをご覧ください。


2

オブジェクトエクスプローラーでテーブル名を右クリックします。いくつかのオプションが表示されます。「デザイン」をクリックします。このテーブルの新しいタブが開きます。ここで '列のプロパティ'にIdentity制約を追加できます。


2

列のIDプロパティを変更するには:

  • サーバーエクスプローラーで、変更するIDプロパティを持つテーブルを右クリックし、[テーブル定義を開く]をクリックします。テーブルデザイナーでテーブルが開きます。
  • 変更する列の[nullを許可する]チェックボックスをオフにします。
  • [列のプロパティ]タブで、[ID仕様]プロパティを展開します。
  • Is Identity子プロパティのグリッドセルをクリックし、ドロップダウンリストから[はい]を選択します。
  • Identity Seedセルに値を入力します。この値は、テーブルの最初の行に割り当てられます。デフォルトでは値1が割り当てられます。

それだけで、私にとってはうまくいきました


2

Visual Studio 2017+を使用している場合

  1. サーバーオブジェクトエクスプローラーでテーブルを右クリックし、[コードの表示]を選択します。
  2. 修飾子「IDENTITY」を列に追加します
  3. 更新

これはあなたのためにそれをすべて行います。


はい!これを提案してくれてありがとう!私はWindows 7ボックスにSSMSのバージョンがありません。これは、2017、SSMSが2014、2017 SSMSがWindows 10を必要とするため、運用サーバーのテーブルのデザインを変更できるバージョンです。VS 2017に移動>サーバーエクスプローラー>本番SQL Serverに新しい接続を作成>テーブルを右クリック> [テーブル定義を開く]> Wala!
JustJohn

実は、私はあなたが右のフィールドをクリックし、[プロパティ]を選択し、そこにはい]を選択するか、番号で識別をすることができた
JustJohn

1

元の投稿者が実際に既存の列をPRIMARY KEYテーブルのに設定することを望んでおり、実際に列を列にする必要がない場合IDENTITY(2つの異なること)、これはt-SQLを介して次のように実行できます。

ALTER TABLE [YourTableName]
ADD CONSTRAINT [ColumnToSetAsPrimaryKey] PRIMARY KEY ([ColumnToSetAsPrimaryKey])

PRIMARY KEYオプションの後の列名を囲む括弧に注意してください。

この投稿は古いものであり、リクエスターの必要性について想定していますが、この追加の情報は、このスレッドに遭遇するユーザーに役立つ可能性があると感じました。会話により、既存の列を正しくない新しい列として追加することなく、主キー。


1

私の現在の状態に従って、私はこのアプローチに従います。スクリプトを使用してデータを挿入した後、プライマリテーブルにIDを付与したいと考えています。

IDを追加したいので、必要なのは常に1からレコードの終わりまでです。

--first drop column and add with identity
ALTER TABLE dbo.tblProductPriceList drop column ID 
ALTER TABLE dbo.tblProductPriceList add ID INT IDENTITY(1,1)

--then add primary key to that column (exist option you can ignore)
IF  NOT EXISTS (SELECT * FROM sys.key_constraints  WHERE object_id = OBJECT_ID(N'[dbo].[PK_tblProductPriceList]') AND parent_object_id = OBJECT_ID(N'[dbo].[tblProductPriceList]'))
    ALTER TABLE [tblProductPriceList] ADD PRIMARY KEY (id)
GO

これにより、IDを持つ同じ主キー列が作成されます

私はこのリンクを使用しました:https : //blog.sqlauthority.com/2014/10/11/sql-server-add-auto-incremental-identity-column-to-table-after-creating-table/

既存のテーブルに主キーを追加する


0

tsqlを使用して既存の列をID列に変更できるとは思いません。ただし、Enterprise Managerのデザインビューから実行できます。

または、ID列として新しい行を作成し、古い列を削除してから、新しい列の名前を変更することもできます。

ALTER TABLE FooTable
ADD BarColumn INT IDENTITY(1, 1)
               NOT NULL
               PRIMARY KEY CLUSTERED

2
SSMS / Enterprise Managerを通じて行う場合は、新しいテーブルを作成し、データをコピーし、古いテーブルを削除し、新しいテーブルの名前を変更することに注意してください。大きなテーブルがあると、かなり高価になる可能性があります...
Scott Ivey

0

基本的に4つの論理ステップがあります。

  1. 新しいID列を作成します。この新しい列のIDの挿入をオンにします。

  2. ソース列(Identityに変換する列)からのデータをこの新しい列に挿入します。

  3. 新しい列のIDの挿入をオフにします。

  4. ソース列をドロップし、新しい列の名前をソース列の名前に変更します。

複数のサーバー間で作業するなど、さらに複雑になる可能性があります。

手順については、次の記事を参照してください(ssmsとT-sqlを使用)。これらの手順は、T-SQLにあまり慣れていない初心者を対象としています。

http://social.technet.microsoft.com/wiki/contents/articles/23816.how-to-convert-int-column-to-identity-in-the-ms-sql-server.aspx


0

IDが設定されていない主キー= bigintを持つすべてのテーブルのスクリプトを生成します。これにより、各テーブルで生成されたスクリプトのリストが返されます。

SET NOCOUNT ON;

declare @sql table(s varchar(max), id int identity)

DECLARE @table_name nvarchar(max),
        @table_schema nvarchar(max);

DECLARE vendor_cursor CURSOR FOR 
SELECT
  t.name, s.name
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
  ON s.[schema_id] = t.[schema_id]
WHERE EXISTS (
    SELECT
    [c].[name]
    from sys.columns [c]
    join sys.types [y] on [y].system_type_id = [c].system_type_id
    where [c].[object_id] = [t].[object_id] and [y].name = 'bigint' and [c].[column_id] = 1
) and NOT EXISTS 
(
  SELECT 1 FROM sys.identity_columns
    WHERE [object_id] = t.[object_id]
) and exists (
    select 1 from sys.indexes as [i] 
    inner join sys.index_columns as [ic]  ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
    where object_name([ic].[object_id]) = [t].[name]
)
OPEN vendor_cursor

FETCH NEXT FROM vendor_cursor 
INTO @table_name, @table_schema

WHILE @@FETCH_STATUS = 0
BEGIN

DELETE FROM @sql

declare @pkname varchar(100),
    @pkcol nvarchar(100)

SELECT  top 1
        @pkname = i.name,
        @pkcol = COL_NAME(ic.OBJECT_ID,ic.column_id)
FROM    sys.indexes AS [i]
INNER JOIN sys.index_columns AS [ic] ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
WHERE   i.is_primary_key = 1 and OBJECT_NAME(ic.OBJECT_ID) = @table_name

declare @q nvarchar(max) = 'SELECT  '+@pkcol+' FROM ['+@table_schema+'].['+@table_name+'] ORDER BY '+@pkcol+' DESC'

DECLARE @ident_seed nvarchar(max) -- Change this to the datatype that you are after
SET @q = REPLACE(@q, 'SELECT', 'SELECT TOP 1 @output = ')
EXEC sp_executeSql @q, N'@output bigint OUTPUT', @ident_seed OUTPUT

insert into  @sql(s) values ('BEGIN TRANSACTION')
insert into  @sql(s) values ('BEGIN TRY')

-- create statement
insert into  @sql(s) values ('create table ['+@table_schema+'].[' + @table_name + '_Temp] (')

-- column list
insert into @sql(s) 
select 
    '  ['+[c].[name]+'] ' +
    y.name + 

    (case when [y].[name] like '%varchar' then
    coalesce('('+(case when ([c].[max_length] < 0 or [c].[max_length] >= 1024) then 'max' else cast([c].max_length as varchar) end)+')','')
    else '' end)

     + ' ' +
    case when [c].name = @pkcol then 'IDENTITY(' +COALESCE(@ident_seed, '1')+',1)' else '' end + ' ' +
    ( case when c.is_nullable = 0 then 'NOT ' else '' end ) + 'NULL ' + 
    coalesce('DEFAULT ('+(
        REPLACE(
            REPLACE(
                LTrim(
                    RTrim(
                        REPLACE(
                            REPLACE(
                                REPLACE(
                                    REPLACE(
                                        LTrim(
                                            RTrim(
                                                REPLACE(
                                                    REPLACE(
                                                        object_definition([c].default_object_id)
                                                    ,' ','~')
                                                ,')',' ')
                                            )
                                        )
                                    ,' ','*')
                                ,'~',' ')
                            ,' ','~')
                        ,'(',' ')
                    )
                )
            ,' ','*')
        ,'~',' ')
    ) +
    case when object_definition([c].default_object_id) like '%get%date%' then '()' else '' end
    +
    ')','') + ','
 from sys.columns c
 JOIN sys.types y ON y.system_type_id = c.system_type_id
  where OBJECT_NAME(c.[object_id]) = @table_name and [y].name != 'sysname'
 order by [c].column_id


 update @sql set s=left(s,len(s)-1) where id=@@identity

-- closing bracket
insert into @sql(s) values( ')' )

insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] ON')

declare @cols nvarchar(max)
SELECT @cols = STUFF(
    (
        select ',['+c.name+']'
        from sys.columns c
        JOIN sys.types y ON y.system_type_id = c.system_type_id
        where c.[object_id] = OBJECT_ID(@table_name)
        and [y].name != 'sysname'
        and [y].name != 'timestamp'
        order by [c].column_id
        FOR XML PATH ('')
     )
    , 1, 1, '')

insert into @sql(s) values( 'IF EXISTS(SELECT * FROM ['+@table_schema+'].['+@table_name+'])')
insert into @sql(s) values( 'EXEC(''INSERT INTO ['+@table_schema+'].['+@table_name+'_Temp] ('+@cols+')')
insert into @sql(s) values( 'SELECT '+@cols+' FROM ['+@table_schema+'].['+@table_name+']'')')

insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] OFF')


insert into @sql(s) values( 'DROP TABLE ['+@table_schema+'].['+@table_name+']')

insert into @sql(s) values( 'EXECUTE sp_rename N''['+@table_schema+'].['+@table_name+'_Temp]'', N'''+@table_name+''', ''OBJECT''')

if ( @pkname is not null ) begin
    insert into @sql(s) values('ALTER TABLE ['+@table_schema+'].['+@table_name+'] ADD CONSTRAINT ['+@pkname+'] PRIMARY KEY CLUSTERED (')
    insert into @sql(s)
        select '  ['+COLUMN_NAME+'] ASC,' from information_schema.key_column_usage
        where constraint_name = @pkname
        GROUP BY COLUMN_NAME, ordinal_position
        order by ordinal_position

    -- remove trailing comma
    update @sql set s=left(s,len(s)-1) where id=@@identity
    insert into @sql(s) values ('  )')
end

insert into  @sql(s) values ('--Run your Statements')
insert into  @sql(s) values ('COMMIT TRANSACTION')
insert into  @sql(s) values ('END TRY')
insert into  @sql(s) values ('BEGIN CATCH')
insert into  @sql(s) values ('        ROLLBACK TRANSACTION')
insert into  @sql(s) values ('        DECLARE @Msg NVARCHAR(MAX)  ')
insert into  @sql(s) values ('        SELECT @Msg=ERROR_MESSAGE() ')
insert into  @sql(s) values ('        RAISERROR(''Error Occured: %s'', 20, 101,@msg) WITH LOG')
insert into  @sql(s) values ('END CATCH')

declare @fqry nvarchar(max)

-- result!
SELECT @fqry = (select char(10) + s from @sql order by id FOR XML PATH (''))


SELECT @table_name as [Table_Name], @fqry as [Generated_Query]
PRINT 'Table: '+@table_name
EXEC sp_executeSql @fqry

    FETCH NEXT FROM vendor_cursor 
    INTO @table_name, @table_schema
END 
CLOSE vendor_cursor;
DEALLOCATE vendor_cursor;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.