SQL Server 데이터베이스가 있고 큰 숫자로 시작 10010
하고 다른 테이블과 관련되어 있기 때문에 ID 열을 변경하고 싶습니다 . 이제 200 개의 레코드가 있으며 레코드가 증가하기 전에이 문제를 해결하려고합니다.
이 항목을 변경하거나 재설정하는 가장 좋은 방법은 무엇입니까?
SQL Server 데이터베이스가 있고 큰 숫자로 시작 10010
하고 다른 테이블과 관련되어 있기 때문에 ID 열을 변경하고 싶습니다 . 이제 200 개의 레코드가 있으며 레코드가 증가하기 전에이 문제를 해결하려고합니다.
이 항목을 변경하거나 재설정하는 가장 좋은 방법은 무엇입니까?
답변:
신원 열을 업데이트 할 수 없습니다.
SQL Server에서는 update 문을 사용하여 다른 열로 수행 할 수있는 것과 달리 ID 열을 업데이트 할 수 없습니다.
비슷한 종류의 요구 사항을 달성하기위한 몇 가지 대안이 있지만.
테이블의 현재 ID 값을 확인하고 필요한 경우 ID 값을 변경하는 DBCC CHECKIDENT 를 사용하십시오 .
DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
사용 IDENTITY_INSERT 명시 적 값을 허용하는 테이블의 식별 컬럼에 삽입합니다.
SET IDENTITY_INSERT YourTable {ON|OFF}
예:
-- Set Identity insert on so that value can be inserted into this column
SET IDENTITY_INSERT YourTable ON
GO
-- Insert the record which you want to update with new value in the identity column
INSERT INTO YourTable(IdentityCol, otherCol) VALUES(13,'myValue')
GO
-- Delete the old row of which you have inserted a copy (above) (make sure about FK's)
DELETE FROM YourTable WHERE ID=3
GO
--Now set the idenetity_insert OFF to back to the previous track
SET IDENTITY_INSERT YourTable OFF
UPDATE YourTable SET IdentityCol = 13
. SET IDENTITY_INSERT YourTable ON
UPDATE가 아닌 INSERT 만 허용합니다.
질문이 바로 있다면 다음과 같은 일을하고 싶습니다.
update table
set identity_column_name = some value
쉬운 과정이 아니며 관련 과정이있을 수 있으므로 사용하지 않는 것이 좋습니다 foreign key
.
그러나 여기 그것을 할 단계는, 테이크 바랍니다 back-up
테이블을
1 단계-테이블의 디자인 뷰 선택
2 단계-ID 열 끄기
이제 update
쿼리를 사용할 수 있습니다 .
이제 redo
1 단계와 2 단계에서 ID 열을 켭니다.
:)
당신은 필요
set identity_insert YourTable ON
그런 다음 행을 삭제하고 다른 ID로 다시 삽입하십시오.
삽입을 완료하면 identity_insert를 끄는 것을 잊지 마십시오
set identity_insert YourTable OFF
--before running this make sure Foreign key constraints have been removed that reference the ID.
--set table to allow identity to be inserted
SET IDENTITY_INSERT yourTable ON;
GO
--insert everything into a temp table
SELECT *
INTO #tmpYourTable
FROM yourTable
--clear your table
DELETE FROM yourTable
--insert back all the values with the updated ID column
INSERT INTO yourTable (IDCol, OtherCols)
SELECT ID+1 as updatedID --put any other update logic to the ID here
, OtherCols FROM #tmpYourTable
--drop the temp table
DROP TABLE #tmpYourTable
--put identity back to normal
SET IDENTITY_INSERT yourTable OFF;
GO
사용해보십시오 DBCC CHECKIDENT
:
DBCC CHECKIDENT ('YourTable', RESEED, 1);
ID 열이없는 새 테이블에 테이블을 복사하십시오.
select columns into newtable from yourtable
새로운 시드로 newtable에 ID 열을 추가하고 기본 키로 만듭니다.
ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY
SET IDENTITY_INSERT dbo.TableName ON
INSERT INTO dbo.TableName
(
TableId, ColumnName1, ColumnName2, ColumnName3
)
VALUES
(
TableId_Value, ColumnName1_Value, ColumnName2_Value, ColumnName3_Value
)
SET IDENTITY_INSERT dbo.TableName OFF
Identity_Insert를 사용할 때 sql은 열 이름을 지정하지 않고 삽입 할 수 없으므로 열 이름을 포함시키는 것을 잊지 마십시오.
또한 SET IDENTITY INSERT
ID 열에 값을 삽입 할 수 있습니다.
예:
SET IDENTITY_INSERT dbo.Tool ON
GO
그런 다음 필요한 값을 ID 열에 삽입 할 수 있습니다.
ALTER TABLE tablename add newcolumn int
update tablename set newcolumn=existingcolumnname
ALTER TABLE tablename DROP COLUMN existingcolumnname;
EXEC sp_RENAME 'tablename.oldcolumn' , 'newcolumnname', 'COLUMN'
update tablename set newcolumnname=value where condition
그러나 위 코드는 1 차 외래 키 관계가없는 경우에만 작동합니다
명령 빌더를 사용하는 C # 프로그래머를위한 완벽한 솔루션
우선, 당신은이 사실을 알아야합니다 :
따라서 일단 알고 있으면해야합니다. 자체 SQL Insert 문을 프로그래밍하거나 insert 명령 빌더를 소유 한 프로그램을 프로그래밍하십시오. 또는 내가 당신을 위해 프로그래밍 한 것을 사용하십시오. DataTable이 주어지면 SQL 삽입 스크립트를 생성합니다.
public static string BuildInsertSQLText ( DataTable table )
{
StringBuilder sql = new StringBuilder(1000,5000000);
StringBuilder values = new StringBuilder ( "VALUES (" );
bool bFirst = true;
bool bIdentity = false;
string identityType = null;
foreach(DataRow myRow in table.Rows)
{
sql.Append( "\r\nINSERT INTO " + table.TableName + " (" );
foreach ( DataColumn column in table.Columns )
{
if ( column.AutoIncrement )
{
bIdentity = true;
switch ( column.DataType.Name )
{
case "Int16":
identityType = "smallint";
break;
case "SByte":
identityType = "tinyint";
break;
case "Int64":
identityType = "bigint";
break;
case "Decimal":
identityType = "decimal";
break;
default:
identityType = "int";
break;
}
}
else
{
if ( bFirst )
bFirst = false;
else
{
sql.Append ( ", " );
values.Append ( ", " );
}
sql.Append ("[");
sql.Append ( column.ColumnName );
sql.Append ("]");
//values.Append (myRow[column.ColumnName].ToString() );
if (myRow[column.ColumnName].ToString() == "True")
values.Append("1");
else if (myRow[column.ColumnName].ToString() == "False")
values.Append("0");
else if(myRow[column.ColumnName] == System.DBNull.Value)
values.Append ("NULL");
else if(column.DataType.ToString().Equals("System.String"))
{
values.Append("'"+myRow[column.ColumnName].ToString()+"'");
}
else
values.Append (myRow[column.ColumnName].ToString());
//values.Append (column.DataType.ToString() );
}
}
sql.Append ( ") " );
sql.Append ( values.ToString () );
sql.Append ( ")" );
if ( bIdentity )
{
sql.Append ( "; SELECT CAST(scope_identity() AS " );
sql.Append ( identityType );
sql.Append ( ")" );
}
bFirst = true;
sql.Append(";");
values = new StringBuilder ( "VALUES (" );
} //fin foreach
return sql.ToString ();
}
먼저 DBCC를 사용한 다음 insert를 사용하여이 문제를 해결했습니다. 예를 들어 테이블이
먼저 테이블에서 새로운 현재 ID 값을 NEW_RESEED_VALUE로 설정하십시오.
MyTable {IDCol, colA, colB}
DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)
그럼 당신은 사용할 수 있습니다
insert into MyTable (colA, ColB) select colA, colB from MyTable
NEW_RESEED_VALUE로 시작하는 새 IDCol 값을 사용하지만 모든 레코드가 복제됩니다. 그런 다음 외래 키 참조 (있는 경우)를 제거 / 이동하면 더 높은 ID 값 중복 행을 제거 할 수 있습니다.
기본 키 값을 다른 숫자 (예 : 123-> 1123)로 변경해야하는 경우 identity 속성은 PK 값 변경을 차단합니다. Set Identity_insert가 작동하지 않습니다. 계단식 삭제가있는 경우 참조 무결성 검사를 해제하지 않는 한 삽입 / 삭제를 수행하지 않는 것이 좋습니다.
이 스크립트는 PK에서 ID를 해제합니다.
***********************
sp_configure 'allow update', 1
go
reconfigure with override
go
update syscolumns set colstat = 0 --turn off bit 1 which indicates identity column
where id = object_id('table_name') and name = 'column_name'
go
exec sp_configure 'allow update', 0
go
reconfigure with override
go
***********************
다음으로 외래 키 참조를 업데이트하도록 관계를 설정할 수 있습니다. 그렇지 않으면 관계 시행을 해제해야합니다. 이 SO 링크는 어떻게 T-SQL을 사용하여 외래 키 제약 조건을 일시적으로 비활성화 할 수 있습니까?를 보여줍니다.
이제 업데이트를 할 수 있습니다. 동일한 열 이름을 기반으로 모든 업데이트 SQL을 작성하는 짧은 스크립트를 작성했습니다 (제 경우에는 CaseID를 1,000,000 씩 늘려야했습니다).
select
'update ['+c.table_name+'] SET ['+Column_Name+']=['+Column_Name+']+1000000'
from Information_Schema.Columns as c
JOIN Information_Schema.Tables as t ON t.table_Name=c.table_name and t.Table_Schema=c.table_schema and t.table_type='BASE TABLE'
where Column_Name like 'CaseID' order by Ordinal_position
마지막으로 참조 무결성을 다시 활성화 한 다음 기본 키에서 ID 열을 다시 활성화하십시오.
참고 :이 질문에 대한 사람들이 WHY를 묻는 것을 보았습니다. 필자의 경우 두 번째 인스턴스를 종료 할 수 있도록 두 번째 프로덕션 인스턴스의 데이터를 마스터 DB로 병합해야합니다. 충돌하지 않으려면 모든 PK / FK 작업 데이터가 필요합니다. 메타 데이터 FK는 동일합니다.