SQL Server में Identity Column को कैसे अपडेट करें?


195

मेरे पास SQL ​​सर्वर डेटाबेस है और मैं पहचान कॉलम को बदलना चाहता हूं क्योंकि यह एक बड़ी संख्या के साथ शुरू हुआ था 10010और यह एक अन्य तालिका से संबंधित है, अब मेरे पास 200 रिकॉर्ड हैं और मैं रिकॉर्ड बढ़ने से पहले इस मुद्दे को ठीक करना चाहता हूं।

इस कॉलम को बदलने या रीसेट करने का सबसे अच्छा तरीका क्या है?

जवाबों:


269

आप पहचान कॉलम को अपडेट नहीं कर सकते।

SQL सर्वर आपके द्वारा अपडेट किए गए स्टेटमेंट के साथ अन्य कॉलमों के विपरीत पहचान कॉलम को अपडेट करने की अनुमति नहीं देता है।

हालांकि इसी तरह की आवश्यकता को प्राप्त करने के लिए कुछ विकल्प हैं।

  • जब पहचान कॉलम का मान नए रिकॉर्ड के लिए अद्यतन किया जाना चाहिए

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

6
DBCC अगले नए रिकॉर्ड को रीसेट करें, लेकिन मैं मौजूदा रिकॉर्ड को बदलना चाहता हूं।
अब्दुस्सलाम एलशरीफ

क्या आप कृपया उदाहरण दे सकते हैं?
अब्दुस्सलाम एलशरीफ

38
@ साचिन यह एक मौजूदा पहचान को अद्यतन नहीं कर रहा है यह मैन्युअल रूप से सम्मिलित कर रहा है
फिल ग्रेगन

3
@PhillGreggan हाँ, यह इसे प्राप्त करने के लिए सबसे अच्छा संभव समाधान है। जैसे ही आप सामान्य को अपडेट करते हैं आप पहचान कॉलम को अपडेट नहीं कर सकते।
सचिन

17
यह स्वीकृत उत्तर प्रश्न का उत्तर नहीं देता है, जो एक पहचान कॉलम (जैसे ) को अद्यतन करने के लिए है UPDATE YourTable SET IdentityCol = 13SET IDENTITY_INSERT YourTable ONकेवल INSERTs को अनुमति देता है, अद्यतन नहीं।
इयान बॉयड

61

यदि आपका प्रश्न सही है तो आप कुछ ऐसा करना चाहते हैं

update table
set identity_column_name = some value

आपको बता दें, यह एक आसान प्रक्रिया नहीं है और इसका उपयोग करना उचित नहीं है, क्योंकि इस foreign keyपर कुछ जुड़े हो सकते हैं ।

लेकिन यहाँ यह करने के लिए कदम हैं, कृपया back-upतालिका का एक हिस्सा लें

चरण 1- तालिका का डिज़ाइन दृश्य चुनें

यहां छवि विवरण दर्ज करें

चरण 2- पहचान कॉलम को बंद करें

यहां छवि विवरण दर्ज करें

अब आप updateक्वेरी का उपयोग कर सकते हैं ।

अब redoचरण 1 और चरण 2 और पहचान कॉलम चालू करें

संदर्भ


1
मेरे पास इस तालिका से संबंधित एक और तालिका है, मुझे लगता है कि मैं ऐसा नहीं कर सकता
अब्दुलसलाम एल्शरिफ़

4
इसलिए यह कथन उचित नहीं है :)
Luv

3
@AbdusalamElsherif लेकिन आपने पूछा कि पहचान कॉलम कैसे बदलना है।
पापाराज़ो

@ वेलव ने कम से कम आपने उस प्रश्न का उत्तर दिया है जिसमें पूछा गया था
फिल ग्रेगन

मैं अपने विकास डेटाबेस में आईडी सेट करने के लिए इस प्रक्रिया का उपयोग करता हूं। यह अच्छा होगा अगर कोई कमांड होती जो मुझे वैसे भी करने देती, लेकिन यह काम करता है।
जेफ डेविस

56

आपको

set identity_insert YourTable ON

फिर अपनी पंक्ति हटाएं और इसे अलग पहचान के साथ पुन: स्थापित करें।

एक बार जब आप सम्मिलित कर लेते हैं तो आइडेंटी_इन्टर को बंद करना न भूलें

set identity_insert YourTable OFF

यह कॉलम के लिए पहचान को बंद करने की तुलना में बहुत आसान और सुरक्षित है!
रक्षक एक

यह बहुत कम संख्या में सुरक्षित और आसान है, लेकिन इस सवाल का ठीक से जवाब नहीं देता है। पहचान को बंद करना, हालांकि अधिक खतरनाक और कभी-कभी असंभव है, आपको पहचान कॉलम को अपडेट करने की अनुमति देता है।
मैथ्यू हडसन

18
--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

1
यदि टेबल पर डिलीट करने के बजाय बस एक परफॉर्मेंस टिप है, तो टेबल पर डिलीट करने के बजाय अपने टेबल को ट्रंचेट करें। यह तात्कालिक है। हालांकि सावधानी बरतना, ट्रंकट के साथ पीछे मुड़ना नहीं है क्योंकि यह लॉग नहीं है।
कुकलेई


5

पहचान तालिका के बिना अपनी तालिका को एक नई तालिका में कॉपी करें।

    select columns into newtable from yourtable

नए बीज के साथ नए के लिए एक पहचान कॉलम जोड़ें और इसे प्राथमिक कुंजी के रूप में बनाएं

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

3
DBCC CHECKIDENT(table_name, RESEED, value)

table_name = वह तालिका दें जिसे आप मान रीसेट करना चाहते हैं

मान = प्रारंभिक मान शून्य होना, 1 के साथ पहचान कॉलम शुरू करना


3
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 आपको उन्हें निर्दिष्ट किए बिना सम्मिलित करने की अनुमति नहीं देगा


2

आप SET IDENTITY INSERTकिसी पहचान स्तंभ में मान सम्मिलित करने की अनुमति देने के लिए भी उपयोग कर सकते हैं ।

उदाहरण:

SET IDENTITY_INSERT dbo.Tool ON
GO

और फिर आप एक पहचान कॉलम में उन मूल्यों को सम्मिलित कर सकते हैं जिनकी आपको आवश्यकता है।


1
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 # प्रोग्रामर्स के लिए पूर्ण समाधान

सबसे पहले, आपको इस तथ्य को जानना होगा:

  • किसी भी स्थिति में, आप एक पहचान कॉलम को संशोधित नहीं कर सकते हैं, इसलिए आपको पंक्ति को हटाना होगा और नई पहचान के साथ फिर से जोड़ना होगा।
  • आप कॉलम से पहचान संपत्ति नहीं निकाल सकते हैं (आपको कॉलम को हटाना होगा)
  • कस्टम कमांड बिल्डर .net से हमेशा पहचान कॉलम को छोड़ता है, इसलिए आप इसे इस उद्देश्य के लिए उपयोग नहीं कर सकते।

तो, एक बार यह जानने के बाद कि आपको क्या करना है। या तो अपने खुद के एसक्यूएल डालें बयान कार्यक्रम, या आप कमांड कमांडर डालने का कार्यक्रम। या आप के लिए प्रोग्राम किया गया है कि इस का उपयोग करें। 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 ();
}

0

मैंने पहले DBCC का उपयोग करके और फिर सम्मिलित का उपयोग करके इस समस्या को हल किया है। उदाहरण के लिए यदि आपकी तालिका है

सबसे पहले टेबल पर नई करेंट आईडी वैल्यू को NEW_RESEED_VALUE के रूप में सेट करें

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

तो आप उपयोग कर सकते हैं

    insert into MyTable (colA, ColB) select colA, colB from MyTable

यह आपके सभी रिकॉर्डों की नक़ल करेगा लेकिन नए IDCol मूल्य का उपयोग करके NEW_RESEED_VALUE के रूप में शुरू होगा। यदि आप अपने विदेशी कुंजी संदर्भों को हटा चुके हैं, तो आप एक बार उच्च ID मान डुप्लिकेट पंक्तियाँ निकाल सकते हैं।


1
यह एक सभ्य विचार है, लेकिन New_reseed_value वर्तमान बीज है, और अगली संख्या जो उपयोग की जाएगी वह उस मूल्य से 1 अधिक होगी। इसलिए यदि आप चाहते हैं कि अगली सम्मिलित पंक्ति पहचान 10 हो, तो NEW_RESEED_VALUE को 9 पर सेट होना चाहिए
लैरीबड

0

आप निम्न कोड का उपयोग करके एक नई तालिका बना सकते हैं।

SELECT IDENTITY (int, 1, 1) AS id, column1, column2
INTO dbo.NewTable
FROM dbo.OldTable

फिर पुरानी डीबी को हटा दें, और नए डीबी को पुराने डीबी के नाम पर नाम दें। नोट : वह कॉलम 1 और कॉलम 2 आपकी पुरानी तालिका के सभी स्तंभों का प्रतिनिधित्व करता है जिन्हें आप अपनी नई तालिका में रखना चाहते हैं।


0

यदि आपको विशेष रूप से प्राथमिक कुंजी मान को किसी भिन्न संख्या (उदा 123 -> 1123) में बदलना है। पहचान संपत्ति ब्लॉक एक PK मान को बदल रहा है। सेट करें Identity_insert काम नहीं करने वाला है। यदि आपके पास कैस्केडिंग डिलीट है (जब तक कि आप संदर्भात्मक अखंडता जाँच बंद नहीं करते हैं) एक इन्सर्ट / डिलीट करना उचित नहीं है।

यह स्क्रिप्ट एक PK पर पहचान को बंद कर देगी:

***********************

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 का उपयोग करके विदेशी कुंजी बाधाओं को अस्थायी रूप से कैसे अक्षम किया जा सकता है?

अब, आप अपने अपडेट कर सकते हैं। मैंने एक ही कॉलम नाम के आधार पर अपने सभी अपडेट एसक्यूएल को लिखने के लिए एक छोटी स्क्रिप्ट लिखी (मेरे मामले में, मुझे केसपी को एफपी द्वारा बढ़ाने की आवश्यकता थी:

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

अंत में, संदर्भात्मक अखंडता को फिर से सक्षम करें और फिर प्राथमिक कुंजी पर पहचान कॉलम को फिर से सक्षम करें।

नोट: मुझे लगता है कि इन सवालों पर कुछ लोग क्यों पूछते हैं। मेरे मामले में, मुझे एक दूसरे उत्पादन उदाहरण से डेटा को एक मास्टर DB में मर्ज करना होगा ताकि मैं दूसरी आवृत्ति को बंद कर सकूं। मुझे बस सभी पीके / एफके को ऑपरेशन डेटा की आवश्यकता है ताकि टकराव न हो। मेटा-डेटा FK समान हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.