प्रोग्राम रूप से पहचान कॉलम मान कैसे बदलें?


160

मेरे पास एक Testकॉलम के साथ एक MS SQL 2005 डेटाबेस है IDIDएक पहचान स्तंभ है।

मेरे पास इस तालिका में पंक्तियाँ हैं और उन सभी के पास अपनी संबंधित आईडी ऑटो संवर्धित मूल्य है।

अब मैं इस तालिका में हर आईडी को इस तरह बदलना चाहूंगा:

ID = ID + 1

लेकिन जब मैं ऐसा करता हूं तो मुझे एक त्रुटि मिलती है:

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

मैंने यह कोशिश की है:

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON

लेकिन इससे समस्या हल नहीं होती है।

मुझे इस कॉलम में पहचान सेट करने की आवश्यकता है, लेकिन मुझे समय-समय पर मूल्यों को बदलने की आवश्यकता है। तो मेरा सवाल है कि इस कार्य को कैसे पूरा किया जाए।

जवाबों:


220

आपको

set identity_insert YourTable ON

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

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

set identity_insert YourTable OFF

133
यह सेटिंग केवल डेटा डालने पर काम करेगी और अपडेट करते समय नहीं। अद्यतन कथन अभी भी विफल रहेगा।
हसीन रोसेविक

31
अपडेट के लिए, आपको हटाने और फिर से डालने की आवश्यकता है। कोई अन्य रास्ता नहीं है।
ashes999

1
@MartinSmith आपका समाधान बहुत लंबा लगता है। इसे दो चरणों में करने में सक्षम होना (पहचान-बंद, हटाना / सम्मिलित करना, पहचान करना) अधिक प्रभावी है।
ashes999

3
@ ashes999 यह 4 चरण है। 2. मेरा उत्तर केवल एक ही है (तालिका बनाएं, स्विच करें, अपडेट करें, वापस स्विच करें, ड्रॉप करें) यह संभवत: आप इन चरणों से अधिक परिचित हैं, इसलिए वे कम जटिल लगते हैं। अद्यतन करना अधिक कुशल हो सकता है तब सम्मिलित करें हटाएं जब कई पंक्तियाँ शामिल हों। इसके अलावा, आप कहाँ हटाए गए पंक्तियों को पकड़ रहे हैं? यदि एक #tempतालिका जिसे आप तब छोड़ते हैं तो वह एक और चरण है जिसे आपने यहां नहीं गिना है।
मार्टिन स्मिथ

40

IDENTITY स्तंभ मान अपरिवर्तनीय हैं।

हालांकि IDENTITYसंपत्ति को हटाने के लिए टेबल मेटाडेटा को स्विच करना संभव है , अपडेट करें, फिर वापस स्विच करें।

निम्न संरचना मानकर

CREATE TABLE Test
(
ID INT IDENTITY(1,1) PRIMARY KEY,
X VARCHAR(10)
)

INSERT INTO Test 
OUTPUT INSERTED.*
SELECT 'Foo' UNION ALL
SELECT 'Bar' UNION ALL
SELECT 'Baz'

तब आप कर सकते हैं

/*Define table with same structure but no IDENTITY*/
CREATE TABLE Temp
(
ID INT PRIMARY KEY,
X VARCHAR(10)
)

/*Switch table metadata to new structure*/
ALTER TABLE Test SWITCH TO Temp;

/*Do the update*/
UPDATE Temp SET ID = ID + 1;

/*Switch table metadata back*/
ALTER TABLE Temp SWITCH TO Test;

/*ID values have been updated*/
SELECT *
FROM Test

/*Safety check in case error in preceding step*/
IF NOT EXISTS(SELECT * FROM Temp)
    DROP TABLE Temp /*Drop obsolete table*/

SQL सर्वर 2012 में यह संभव है कि एक ऑटो इंक्रीमेंटिंग कॉलम हो जिसे और भी सरलता से अपडेट किया जा सके SEQUENCES

CREATE SEQUENCE Seq
    AS INT
    START WITH 1
    INCREMENT BY 1

CREATE TABLE Test2
(
ID INT DEFAULT NEXT VALUE FOR Seq NOT NULL PRIMARY KEY,
X VARCHAR(10)
)

INSERT INTO Test2(X)
SELECT 'Foo' UNION ALL
SELECT 'Bar' UNION ALL
SELECT 'Baz'

UPDATE Test2 SET ID+=1

1
बहुत चालाक है। हर दिन कुछ नया सीखें (BTW मैंने इसे SQLExpress पर परीक्षण किया, इसके बावजूद SWITCH के बावजूद यह विभाजन, स्पष्ट रूप से उपयोग नहीं करता है)। ध्यान दें कि तालिका को बहुत सटीक रूप से मेल खाना है (अनुक्रमित,
एफके

1
जब आपके पास पीके, एफके, इंडेक्स और मूल तालिका में निर्मित दृश्य होते हैं तो क्या स्विच विधि काम करती है? क्या वे इस पद्धति का उपयोग करके टूटेंगे?
tj

1
जब सभी अनुक्रमित और अड़चनों सहित स्रोत तालिका से बाहर तालिका तालिका स्क्रिप्ट बनाते समय @tj। फिर टकराव से बचने के लिए तालिका और बाधाओं के नाम बदलें। जब तक अनुक्रमित या स्कीमाबाउंड नहीं होता, तब तक दृश्य समस्या नहीं होगी।
मार्टिन स्मिथ

यदि टेबल पर एक पूर्ण-पाठ खोज सूचकांक है तो काम नहीं करता है। मुझे लगता है कि इसे हटाने और बाद में इसे फिर से बनाना संभव है, लेकिन मैंने परीक्षण नहीं किया है।
यूएन

26

SQL Server 2005 प्रबंधक में UI के माध्यम से, कॉलम के ऑटोनम्बर (पहचान) की संपत्ति को हटाने वाले कॉलम को बदलें (सही पर क्लिक करके तालिका का चयन करें और "डिज़ाइन" चुनें)।

फिर अपनी क्वेरी चलाएँ:

UPDATE table SET Id = Id + 1

फिर कॉलम में ऑटोनंबर प्रॉपर्टी को वापस जाएं।


3
यदि आप मैन्युअल रूप से परिवर्तन करते हैं, तो आप परिवर्तन के लिए SQL स्क्रिप्ट (तालिका डिज़ाइनर मेनू, परिवर्तन स्क्रिप्ट उत्पन्न) के लिए प्रबंधक से पूछ सकते हैं। इस परिवर्तन के लिए यह एक नई तालिका बनाता है और डेटा की प्रतिलिपि बनाता है, फिर मूल को हटा देता है।
रॉबिन बेनेट

2
@tomaszs - एक कोड उदाहरण जो अधिक कुशल भी है क्योंकि यह शारीरिक रूप से तालिका को बिल्कुल भी पुनर्निर्माण नहीं करता है (यह दो बार ऐसा करेगा) मेरे देर से जवाब में है
मार्टिन स्मिथ

आप पहचान वापस नहीं जोड़ सकते। क्या आप? stackoverflow.com/questions/1049210/…
टॉमस कुब्स

धन्यवाद। यह एकदम सही था। मेरी तालिका में 1 पंक्ति थी, जिसके बारे में मुझे जानकारी नहीं थी, इसलिए मेरी तालिका के लिए मेरी बूटस्ट्रैप स्क्रिप्ट Idमें 1. से ऑटो आइडेंटिटी वैल्यू थी।
शिव

18

सबसे पहले उस मामले के लिए IDENTITY_INSERT चालू या बंद करना आपके लिए आवश्यक चीज़ों के लिए काम नहीं करेगा (इसका उपयोग नए मूल्यों को सम्मिलित करने के लिए किया जाता है, जैसे कि अंतराल को रोकना)।

GUI के माध्यम से ऑपरेशन करने से सिर्फ एक अस्थायी तालिका बनती है, एक पहचान क्षेत्र के बिना एक नया टेबल भर में सभी डेटा की प्रतिलिपि बनाता है, और तालिका का नाम बदल देता है।


9

यह एक अस्थायी तालिका का उपयोग करके किया जा सकता है।

विचार

  • विकलांगों को अक्षम करें (यदि आपकी आईडी एक विदेशी कुंजी द्वारा संदर्भित है)
  • नई आईडी के साथ एक अस्थायी तालिका बनाएं
  • तालिका सामग्री हटाएं
  • कॉपी किए गए टेबल से अपनी मूल तालिका में डेटा कॉपी करें
  • पहले से अक्षम विकलांगों को सक्षम करें

SQL क्वेरीज़

मान लें कि आपकी testतालिका में दो अतिरिक्त कॉलम हैं ( column2और column3) और 2 टेबल हैं जिनमें विदेशी कुंजी संदर्भित हैं और testजिन्हें (क्योंकि वास्तविक जीवन की समस्याएं कभी भी सरल नहीं होती हैं)।foreign_table1foreign_table2

alter table test nocheck constraint all;
alter table foreign_table1 nocheck constraint all;
alter table foreign_table2 nocheck constraint all;
set identity_insert test on;

select id + 1 as id, column2, column3 into test_copy from test v;
delete from test;
insert into test(id, column2, column3)
select id, column2, column3 from test_copy

alter table test check constraint all;
alter table foreign_table1 check constraint all;
alter table foreign_table2 check constraint all;
set identity_insert test off;
drop table test_copy;

बस।


6

DBCC CHECKIDENT ('databasename.dbo.orders', RESEED, 999) आप इस कमांड के साथ किसी भी पहचान कॉलम नंबर को बदल सकते हैं, और आप उस फ़ील्ड नंबर को हर उस नंबर से भी शुरू कर सकते हैं, जिसे आप चाहते हैं। उदाहरण के लिए मेरी कमांड से शुरू करने के लिए कहें। 1000 (999 + 1) को उम्मीद है कि यह पर्याप्त होगा ... शुभकामनाएं


4

यदि स्तंभ पीके नहीं है तो आप हमेशा बढ़े हुए नंबरों के साथ तालिका में एक नया स्तंभ बना सकते हैं, मूल को गिरा सकते हैं और फिर पुराने होने के लिए नए को बदल सकते हैं।

आप ऐसा करने की आवश्यकता क्यों कर सकते हैं के लिए उत्सुक ... सबसे अधिक मुझे कभी पहचान स्तंभों के साथ वायदा करना पड़ा था संख्याओं को बैकफ़िल करना था और मैंने बस DBCC CHECKIDENT (टैबलेन, RESEED, newnextnumber) का उपयोग करके समाप्त किया

सौभाग्य!


1

पहचान संशोधन कई कारकों के आधार पर विफल हो सकता है, मुख्य रूप से आईडी कॉलम से जुड़ी वस्तुओं / रिश्तों के आसपास घूम रहा है। ऐसा लगता है जैसे डीबी डिज़ाइन यहाँ मुद्दा है क्योंकि आईडी को शायद ही कभी बदलना चाहिए (अगर मुझे यकीन है कि आपके पास अपने कारण हैं और बदलावों को याद कर रहे हैं)। यदि आपको वास्तव में समय-समय पर आईडी बदलने की आवश्यकता है, तो मैं आपको एक नया डमी आईडी कॉलम बनाने का सुझाव दूंगा जो प्राथमिक कुंजी / ऑटोनम्बर नहीं है जिसे आप स्वयं प्रबंधित कर सकते हैं और वर्तमान मानों से उत्पन्न कर सकते हैं। यदि आपके पास पहचान सम्मिलित करने की अनुमति के साथ समस्या हो रही है, तो वैकल्पिक रूप से, ऊपर क्रिसटॉफ़र्स विचार मेरा अन्य सुझाव होगा।

सौभाग्य

PS यह विफल नहीं हो रहा है क्योंकि यह जिस क्रमिक क्रम में चल रहा है, वह सूची में एक मूल्य को आइटम के लिए अद्यतन करने का प्रयास कर रहा है जो पहले से ही आईडी की सूची में मौजूद है? तिनके पर चढ़ना, शायद पंक्तियों की संख्या + 1 जोड़ते हैं, तो अगर वह काम करता है पंक्तियों की संख्या घटाना: -S


1

यदि आपको कभी-कभी आईडी बदलने की आवश्यकता होती है, तो संभवतः पहचान कॉलम का उपयोग न करना सबसे अच्छा है। अतीत में हमने 'काउंटर' तालिका का उपयोग करके मैन्युअल रूप से ऑटोनम्बर फ़ील्ड लागू किया है जो प्रत्येक तालिका के लिए अगली आईडी को ट्रैक करता है। IIRC हमने ऐसा इसलिए किया क्योंकि पहचान कॉलम SQL2000 में डेटाबेस भ्रष्टाचार का कारण बन रहे थे लेकिन आईडी बदलने में सक्षम होने के कारण कभी-कभार परीक्षण के लिए उपयोगी था।


1

आप नई पंक्तियों को संशोधित मूल्यों के साथ सम्मिलित कर सकते हैं और फिर पुरानी पंक्तियों को हटा सकते हैं। उदाहरण के बाद आईडी बदलकर विदेशी कुंजी पर्सनडी के समान हो

SET IDENTITY_INSERT [PersonApiLogin] ON

INSERT INTO [PersonApiLogin](
       [Id]
      ,[PersonId]
      ,[ApiId]
      ,[Hash]
      ,[Password]
      ,[SoftwareKey]
      ,[LoggedIn]
      ,[LastAccess])
SELECT [PersonId]
      ,[PersonId]
      ,[ApiId]
      ,[Hash]
      ,[Password]
      ,[SoftwareKey]
      ,[LoggedIn]
      ,[LastAccess]
FROM [db304].[dbo].[PersonApiLogin]
GO

DELETE FROM [PersonApiLogin]
WHERE [PersonId] <> ID
GO
SET IDENTITY_INSERT [PersonApiLogin] OFF
GO

1

सबसे पहले सभी आईडी को सहेजें और उन्हें उन मानों के लिए प्रोग्रामेटिक रूप से बदल दें, जिन्हें आप डेटाबेस से हटाते हैं और फिर उन्हें कुछ के लिए फिर से सम्मिलित करते हैं:

use [Name.Database]
go
set identity_insert [Test] ON
insert into [dbo].[Test]
           ([Id])
     VALUES
           (2)
set identity_insert [Test] OFF

थोक डालने के लिए उपयोग करें:

use [Name.Database]
go
set identity_insert [Test] ON
BULK INSERT [Test]
FROM 'C:\Users\Oscar\file.csv'
WITH (FIELDTERMINATOR = ';',
      ROWTERMINATOR = '\n',
      KEEPIDENTITY)
set identity_insert [Test] OFF

File.csv से नमूना डेटा:

2;
3;
4;
5;
6;

यदि आप identity_insertबंद नहीं करते हैं तो आपको निम्नलिखित त्रुटि मिलेगी:

IDENTITY_INSERT को बंद पर सेट किए जाने पर तालिका 'टेस्ट' में पहचान कॉलम के लिए स्पष्ट मूल्य नहीं डाला जा सकता।


0

मैंने एक अच्छा लेख देखा, जिसने आखिरी समय में मेरी मदद की .. मैं एक तालिका में कुछ पंक्तियों को सम्मिलित करने की कोशिश कर रहा था, जिसमें पहचान कॉलम था लेकिन यह गलत तरीके से था और इसे वापस हटाना पड़ा। एक बार जब मैंने पंक्तियों को हटा दिया तो मेरा पहचान कॉलम बदल गया। मैं उस कॉलम को अपडेट करने का एक तरीका खोजने की कोशिश कर रहा था जो डाला गया था लेकिन - कोई भाग्य नहीं। इसलिए, Google पर खोज करते समय एक लिंक मिला ..

  1. उन स्तंभों को हटा दिया गया था जो गलत तरीके से डाले गए थे
  2. पर / बंद पहचान का उपयोग कर बल डालने का प्रयोग करें (नीचे समझाया गया है)

http://beyondrelational.com/modules/2/blogs/28/posts/10337/sql-server-how-do-i-insert-an-explicit-value-into-an-identity-column-how-do- i-अद्यतन-मूल्य-ऑफ-द an.aspx


1
यकीन नहीं है कि आपने वास्तव में यहां सवाल का जवाब दिया है, हालांकि।
एंड्रयू बार्बर

0

बहुत अच्छा सवाल, पहले हमें विशिष्ट तालिका के लिए IDENTITY_INSERT पर , उसके बाद सम्मिलित क्वेरी (स्तंभ का नाम निर्दिष्ट करना होगा) को चलाने की आवश्यकता है।

नोट: पहचान कॉलम संपादित करने के बाद, IDENTITY_INSERT बंद करना न भूलें । यदि आपने नहीं किया है, तो आप पहचान तालिका को किसी अन्य तालिका के लिए संपादित करने में सक्षम नहीं हो सकते।

SET IDENTITY_INSERT Emp_tb_gb_Menu ON
     INSERT Emp_tb_gb_Menu(MenuID) VALUES (68)
SET IDENTITY_INSERT Emp_tb_gb_Menu OFF

http://allinworld99.blogspot.com/2016/07/how-to-edit-identity-field-in-sql.html

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