回答:
IDの既存の列を変更することはできません。
2つのオプションがあります。
IDを使用して新しいテーブルを作成し、既存のテーブルを削除します
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)
、主キー列を持つ部品を追加できます
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;
これは他の回答の解決策よりも明らかに複雑ですが、テーブルが大きい場合、これは実際の命の恩人になります。いくつかの注意点があります:
上記の要件について詳しく説明した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...SWITCH
DBCC CHECKIDENT
明らかに、新しい行がテーブルに追加されていない場合(または、毎日のETLプロセスのように時々追加されるだけの場合)、この競合状態は発生しないので問題DBCC CHECKIDENT
ありません。
DBCC CHECKIDENT('<newTableName>')
切り替え直後に実行することを検討してください。詳細については、msdn.microsoft.com / en-us / library / ms176057.aspxを参照してください。
列を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'
マーク
ここで説明されているクールなソリューションがあります: SQLサーバー-列のIDプロパティの追加または削除
簡単に説明すると、SQL Managerでテーブルを手動で編集し、IDを切り替え、変更を保存せず、変更用に作成されるスクリプトを表示し、コピーして後で使用します。
変更するテーブルに関連するすべての外部キー、インデックスなどがスクリプトに含まれているため、時間を大幅に節約できます。これを手動で書く...神は禁じた。
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
ここから:列のデフォルト値としてのシーケンス
簡単な説明
sp_RENAMEを使用して既存の列の名前を変更する
EXEC sp_RENAME 'Table_Name.Existing_ColumnName'、 'New_ColumnName'、 'COLUMN'
名前変更の例:
既存の列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を追加しました。
私はたまたま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]';
最後に、すべてがうまくいきました!
そのようにすることはできません。別の列を追加し、元の列をドロップして新しい列の名前を変更するか、新しいテーブルを作成するか、データをコピーして古いテーブルをドロップしてから、新しいテーブルの名前を古い名前に変更する必要がありますテーブル
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
システムテーブルをハッキングしてビット単位の値を設定する方法はあると述べましたが、これはサポートされていないため、実行しません
私は、通常のケースでは理解されているように、私たちはしてテーブルを作成しているプライマリキー持っているアイデンティティプロパティ
だから、名前を変更または削除に関連付けられている列主キーの 制約は、制約ルールが列構造を検証するために行うことはできません。
:これは、我々は次のようにいくつかのステップを処理する必要が達成ット
たちは仮定しようテーブル名=「従業員」とColumnNameのを=「社員」
1.「従業員」テーブルに新しい列「EmployeeId_new」を追加
ALTER TABLE従業員がEmployeeId_new INT IDENTITYを(ADD 1,1)
次に、 'Employee'テーブルから列 'EmployeeId'を削除します
ALTER TABLE Employee DROP COLUMN EmployeeId
主キー制約ルールが適用可能であり、列構造を検証しているため、これはエラーをスローします。
* ### ' メッセージ5074、レベル16、状態1、行1オブジェクト[PK_dbo.Employee]はcolmn [EmployeeId]に依存しています。###
したがって、まずテーブル 'Employee'から主キー制約を削除する必要があります。次に、列ALTER TABLE Employee DROP制約[PK_dbo.Employee]を削除できます
。
これで、ALTER TABLE Employee DROP COLUMN EmployeeIdエラーが発生した前の手順で行ったように、「EmployeeId」列を「Employee」テーブルから削除できます。
列「EmployeeId」がテーブルから削除されたので、新しく追加された新しい列「EmployeeId_new」の名前を「EmployeeId」で変更し
ますsp_rename 'Employee.EmployeeId'、 'EmployeeId_new'、 'COLUMN'
テーブルを以前と同じ形式に再配置するには、列 'EmployeeId'に主キー制約を追加する必要があります
ALTER TABLE Employee追加制約[PK_dbo.Employee]主キー(EmployeeId)
8. これで、「EmployeeId」を持つテーブル「Employee」が、既存の主キー制約とともにIdentityルール用に変更されました。
設計上、既存の列のID機能をオンまたはオフにする簡単な方法はありません。これを行う唯一のクリーンな方法は、新しい列を作成してそれをID列にするか、新しいテーブルを作成してデータを移行することです。
SQL Server Management Studioを使用して列 "id"のID値を削除すると、新しい一時テーブルが作成され、データが一時テーブルに移動され、古いテーブルが削除され、新しいテーブルの名前が変更されます。
Management Studioを使用して変更を行い、デザイナーで右クリックして[変更スクリプトの生成]を選択します。
これは、SQLサーバーがバックグラウンドで実行していることです。
列のIDプロパティを変更するには:
それだけで、私にとってはうまくいきました
Visual Studio 2017+を使用している場合
これはあなたのためにそれをすべて行います。
元の投稿者が実際に既存の列をPRIMARY KEY
テーブルのに設定することを望んでおり、実際に列を列にする必要がない場合IDENTITY
(2つの異なること)、これはt-SQLを介して次のように実行できます。
ALTER TABLE [YourTableName]
ADD CONSTRAINT [ColumnToSetAsPrimaryKey] PRIMARY KEY ([ColumnToSetAsPrimaryKey])
PRIMARY KEY
オプションの後の列名を囲む括弧に注意してください。
この投稿は古いものであり、リクエスターの必要性について想定していますが、この追加の情報は、このスレッドに遭遇するユーザーに役立つ可能性があると感じました。会話により、既存の列を正しくない新しい列として追加することなく、主キー。
私の現在の状態に従って、私はこのアプローチに従います。スクリプトを使用してデータを挿入した後、プライマリテーブルに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/
tsqlを使用して既存の列をID列に変更できるとは思いません。ただし、Enterprise Managerのデザインビューから実行できます。
または、ID列として新しい行を作成し、古い列を削除してから、新しい列の名前を変更することもできます。
ALTER TABLE FooTable
ADD BarColumn INT IDENTITY(1, 1)
NOT NULL
PRIMARY KEY CLUSTERED
基本的に4つの論理ステップがあります。
新しいID列を作成します。この新しい列のIDの挿入をオンにします。
ソース列(Identityに変換する列)からのデータをこの新しい列に挿入します。
新しい列のIDの挿入をオフにします。
ソース列をドロップし、新しい列の名前をソース列の名前に変更します。
複数のサーバー間で作業するなど、さらに複雑になる可能性があります。
手順については、次の記事を参照してください(ssmsとT-sqlを使用)。これらの手順は、T-SQLにあまり慣れていない初心者を対象としています。
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;