तालिका में पहचान कॉलम के लिए एक स्पष्ट मूल्य केवल तब निर्दिष्ट किया जा सकता है जब एक कॉलम सूची का उपयोग किया जाता है और IDENTITY_INSERT SQL सर्वर पर है


187

मैं यह क्वेरी करने की कोशिश कर रहा हूं

INSERT INTO dbo.tbl_A_archive
  SELECT *
  FROM SERVER0031.DB.dbo.tbl_A

लेकिन उसके बाद भी मैं भागा

set identity_insert dbo.tbl_A_archive on

मुझे यह त्रुटि संदेश मिल रहा है

तालिका 'dbo.tbl_A_archive' में पहचान स्तंभ के लिए एक स्पष्ट मूल्य केवल तब निर्दिष्ट किया जा सकता है जब स्तंभ सूची का उपयोग किया जाता है और IDENTITY_INSERT चालू होता है।

tbl_Aपंक्तियों और चौड़ाई में एक विशाल तालिका है, अर्थात इसमें बहुत सारे स्तंभ हैं। मैं सभी कॉलमों को मैन्युअल रूप से टाइप करना नहीं चाहता। में इससे कैसे चला सकता हूँ?


मैं पहले से ही एक तरह से एक जुड़े सर्वर सेटअप है!
jhowe

4
मैं इस समस्या के रूप में अच्छी तरह से कर रहा हूँ, "एक्स सिलेक्ट में डालें * Y" को छोड़कर जब तक मैंने टेबल स्कीमा नहीं बदला, तब तक कोई समस्या नहीं थी
FistOfFury

जवाबों:


79

सारांश

जब तक आप कॉलम सूची का उपयोग नहीं करते हैं, SQL सर्वर आपको किसी पहचान स्तंभ में एक स्पष्ट मान सम्मिलित नहीं करने देगा। इस प्रकार, आपके पास निम्नलिखित विकल्प हैं:

  1. स्तंभ सूची बनाएं (या तो मैन्युअल रूप से या टूल का उपयोग करके, नीचे देखें)

या

  1. पहचान कॉलम को tbl_A_archiveएक नियमित, गैर- पहचान कॉलम में बनाएं : यदि आपकी तालिका एक संग्रह तालिका है और आप हमेशा पहचान कॉलम के लिए एक स्पष्ट मूल्य निर्दिष्ट करते हैं, तो आपको पहचान कॉलम की भी आवश्यकता क्यों है? इसके बजाय बस एक नियमित इंट का उपयोग करें।

समाधान 1 पर विवरण

के बजाय

SET IDENTITY_INSERT archive_table ON;

INSERT INTO archive_table
  SELECT *
  FROM source_table;

SET IDENTITY_INSERT archive_table OFF;

आपको लिखने की जरूरत है

SET IDENTITY_INSERT archive_table ON;

INSERT INTO archive_table (field1, field2, ...)
  SELECT field1, field2, ...
  FROM source_table;

SET IDENTITY_INSERT archive_table OFF;

साथ field1, field2, ...अपनी तालिकाओं में सभी स्तंभों के नामों वाले। यदि आप कॉलम की उस सूची को ऑटो-जनरेट करना चाहते हैं, तो डेव के उत्तर या एंडोमर के उत्तर पर एक नज़र डालें ।


समाधान 2 पर विवरण

दुर्भाग्य से, पहचान पहचान कॉलम के "प्रकार" को केवल गैर-पहचान अंतर कॉलम में बदलना संभव नहीं है। मूल रूप से, आपके पास निम्नलिखित विकल्प हैं:

  • यदि संग्रह तालिका में अभी तक डेटा नहीं है, तो कॉलम को छोड़ दें और पहचान के बिना एक नया जोड़ें।

या

  • अपने संग्रह तालिका में पहचान कॉलम की Identity Specification/ (Is Identity)संपत्ति सेट करने के लिए SQL सर्वर प्रबंधन स्टूडियो का उपयोग करें No। पर्दे के पीछे, यह तालिका को फिर से बनाने और मौजूदा डेटा की प्रतिलिपि बनाने के लिए एक स्क्रिप्ट बनाएगा, इसलिए, ऐसा करने के लिए, आपको भी परेशान होना पड़ेगा Tools/ Options/ Designers/ Table and Database Designers/ Prevent saving changes that require table re-creation

या


1
आपके निचले समाधान के लिए: यदि कॉलम में "पहचान (1, 1)" या ऐसा कुछ है, तो उसे अस्थायी रूप से भी हटाने की आवश्यकता होगी।
Aleksandr Khomenko

1
@AleksandrKhomenko: हाँ, इसका मतलब है कि मैं "इसे [एक नियमित ( गैर-पहचान ) इंट कॉलम" बनाता हूं ।
हेनजी

1
गलतफहमी के लिए खेद है। मेरा वास्तव में मतलब था कि उसे ऑटो-इन्क्रीमेंट प्रॉपर्टी को भी हटाना होगा । एसक्यूएल-सर्वर के मामले में यह "पहचान (1, 1)" कहता है - आपका उत्तर बिल्कुल सही है। लेकिन MySQL और Oracle के पास इसके लिए एक और कमांड है (और यह गैर-स्पष्ट हो जाता है, कृपया w3schools.com/sql/sql_autoincrement.asp पर देखें )
Aleksandr Khomenko

2
इसकी विस्तार से कमी है। मैं समझता हूं कि यह कुछ के लिए रटे हो सकता है लेकिन यह दूसरों के लिए बकवास है
डीजे।

1
@DJ: मैंने कुछ विवरण जोड़े हैं।
हेंजी

332
SET IDENTITY_INSERT tableA ON

आपको अपने INSERT स्टेटमेंट के लिए एक कॉलम सूची बनानी होगी:

INSERT Into tableA ([id], [c2], [c3], [c4], [c5] ) 
SELECT [id], [c2], [c3], [c4], [c5] FROM tableB

"INSERT टेबल में चयन करें ........" की तरह नहीं

SET IDENTITY_INSERT tableA OFF

17
+1 ... आपको केवल क्वेरी के सेलेक्ट क्लॉज में स्पष्ट कॉलम की आवश्यकता है। आप क्वेरी के INSERT क्लॉज में एक तारांकन चिह्न रख सकते हैं
MacGyver

8
... जब तक कि लक्ष्य के पास एक पहचान स्तंभ नहीं है, और स्रोत तालिका में एक पहचान स्तंभ नहीं है
MacGyver

1
यह उत्तर हीनज़ी की तुलना में थोड़ा अधिक स्पष्ट है क्योंकि इसमें SET IDENTITY_INSERT का उल्लेख है
मार्टी

4
+1 आकर्षण की तरह काम करता है! हालांकि, "आप क्वेरी के INSERT क्लॉज में एक तारांकन चिह्न रख सकते हैं" यहां काम नहीं करेगा।
शाय अलोन

1
मुझे यह त्रुटि तब हुई जब चुनिंदा खंड के कॉलम गंतव्य तालिका के साथ मेल नहीं खाते थे। यह सुनिश्चित करते हुए, सम्मिलित ने मेरे लिए काम किया
जोस

39

यदि आप SQL सर्वर प्रबंधन स्टूडियो का उपयोग कर रहे हैं, तो आपको कॉलम सूची को स्वयं टाइप करने की आवश्यकता नहीं है - बस ऑब्जेक्ट एक्सप्लोरर में तालिका पर राइट-क्लिक करें और स्क्रिप्ट तालिका को इस रूप में चुनें -> का चयन करें -> नई क्वेरी संपादक विंडो

यदि आप नहीं हैं, तो इसके समान एक क्वेरी को शुरुआती बिंदु के रूप में मदद करनी चाहिए:

SELECT SUBSTRING(
    (SELECT ', ' + QUOTENAME(COLUMN_NAME)
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'tbl_A'
        ORDER BY ORDINAL_POSITION
        FOR XML path('')),
    3,
    200000);

2
यह एक चर में चुना जा सकता है और गतिशील SQL क्वेरी में उपयोग किया जा सकता है। आपने मेरा दिन बचाया। आपका बहुत बहुत धन्यवाद!
पावेल कियोच

1
धन्यवाद! मैंने इसे इसके साथ बनाया है। gith.github.com/timabell/0ddd6a69565593f907c7
टिम एबेल

वाह। मैं गतिशील रूप से अपनी क्वेरी बनाने के लिए इसे देखने के लिए बेताब था। यहां यह देखकर आश्चर्य हुआ। धन्यवाद दोस्त।
यासीन बिलीर

23

हेनजी के जवाब से सहमत हैं। पहले दूसरे विकल्प के लिए, यहाँ एक क्वेरी है जो एक तालिका में कॉलम की अल्पविराम से अलग सूची बनाती है:

select name + ', ' as [text()] 
from sys.columns 
where object_id = object_id('YourTable') 
for xml path('')

बड़ी तालिकाओं के लिए, यह बहुत सारे टाइपिंग कार्य बचा सकता है :)


@ धन्यवाद, वास्तव में मददगार। :)
चिराग ठाकर

कभी-कभी आपको बस एक व्यावहारिक समाधान की आवश्यकता होती है। धन्यवाद!
टोबियास फील

15

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

वैकल्पिक रूप से आप अनुमति दे सकते हैं और निम्न कथन के साथ तालिका के लिए पहचान आवेषण को अस्वीकार कर सकते हैं

SET IDENTITY_INSERT tbl_A_archive ON
--Your inserts here
SET IDENTITY_INSERT tbl_A_archive OFF

अंत में, यदि आपको काम करने के लिए पहचान कॉलम की आवश्यकता है, तो आप हमेशा केवल संग्रहीत संग्रह चला सकते हैं।

sp_columns tbl_A_archive 

यह आपको तालिका से उन सभी कॉलमों को लौटा देगा जिन्हें आप तब काट सकते हैं और अपनी क्वेरी में पेस्ट कर सकते हैं। (यह एक * का उपयोग करने से बेहतर लगभग है)


11

SQL कथन के लिए, आपको कॉलम सूची भी निर्दिष्ट करनी होगी। उदाहरण के लिए।

INSERT INTO tbl (idcol1,col2) VALUES ( value1,value2)

के बजाय

INSERT INTO tbl VALUES ( value1,value2)

2
यह ओपी के बयान के लिए मामला नहीं है। मानों की आवश्यकता नहीं है यदि INSERT INTO का चयन कथन द्वारा किया जाता है। कृपया अपना उत्तर संशोधित करें या निकालें।
गैरी

4

दोनों काम करेंगे लेकिन अगर आप अभी भी # 1 का उपयोग करके त्रुटि प्राप्त करते हैं तो # 2 के लिए जाएं

1)

SET IDENTITY_INSERT customers ON
GO
insert into dbo.tbl_A_archive(id, ...)
SELECT Id, ...
FROM SERVER0031.DB.dbo.tbl_A

2)

SET IDENTITY_INSERT customers ON
GO
insert into dbo.tbl_A_archive(id, ...)
VALUES(@Id,....)

4
अगर ओपी कई रिकॉर्ड्स डाल रहा है तो यह वास्तव में जाने का तरीका नहीं है। आप अनदेखा कर रहे हैं "tbl_A पंक्तियों और चौड़ाई में एक बड़ी तालिका है, अर्थात इसमें बहुत सारे कॉलम हैं। मैं सभी कॉलमों को मैन्युअल रूप से टाइप करना नहीं चाहता।"
गैरी

4

इस प्रश्न के लिए बताए गए समाधानों के लिए चयन कथन के लिए सभी कॉलम नामों को अल्पविराम-सीमांकित सूची में बदलने के लिए, मैं निम्नलिखित विकल्पों का उपयोग करता हूं क्योंकि वे यहां अधिकांश प्रतिक्रियाओं की तुलना में थोड़ी कम क्रिया हैं। हालांकि, यहां अधिकांश प्रतिक्रियाएं अभी भी पूरी तरह से स्वीकार्य हैं, हालांकि।

1)

SELECT column_name + ',' 
FROM   information_schema.columns 
WHERE  table_name = 'YourTable'

2) यह संभवतः कॉलम बनाने का सबसे सरल तरीका है, यदि आपके पास SQL ​​Server SSMS है।

1) ऑब्जेक्ट एक्सप्लोरर में तालिका पर जाएं और तालिका नाम के बाईं ओर + पर क्लिक करें या उप सूची खोलने के लिए तालिका नाम पर डबल-क्लिक करें।

2) कॉलम सबफ़ोल्डर को मुख्य क्वेरी क्षेत्र पर खींचें और यह आपके लिए संपूर्ण कॉलम सूची को स्वतः खो देगा।


3

आपको कॉलम नाम निर्दिष्ट करना होगा, जिसे आप पहचान कॉलम चाहते हैं। तो कमांड इस तरह होगी:

SET IDENTITY_INSERT DuplicateTable ON

INSERT Into DuplicateTable ([IdentityColumn], [Column2], [Column3], [Column4] ) 
SELECT [IdentityColumn], [Column2], [Column3], [Column4] FROM MainTable

SET IDENTITY_INSERT DuplicateTable OFF

यदि आपकी तालिका में कई कॉलम हैं तो इस कमांड का उपयोग करके उन कॉलम का नाम प्राप्त करें।

SELECT column_name + ','
FROM   information_schema.columns 
WHERE  table_name = 'TableName'
for xml path('')

(अंतिम अल्पविराम (',') को हटाने के बाद) बस पिछले कॉलम का नाम कॉपी करें।


3

यह काम करना चाहिए। मैं सिर्फ आपके मुद्दे में भाग गया:

SET IDENTITY_INSERT dbo.tbl_A_archive ON;
INSERT INTO     dbo.tbl_A_archive (IdColumn,OtherColumn1,OtherColumn2,...)
SELECT  *
FROM        SERVER0031.DB.dbo.tbl_A;
SET IDENTITY_INSERT dbo.tbl_A_archive OFF;

दुर्भाग्य से ऐसा लगता है कि आपको पहचान सम्मिलित करने के लिए पहचान स्तंभ सहित स्तंभों की एक सूची की आवश्यकता है जो पहचान निर्दिष्ट करते हैं। हालाँकि , आपको स्तंभ का चयन करने के लिए सूची में नहीं है। जैसा कि @Dave Cluderay ने सुझाव दिया है कि यह आपको कॉपी और पेस्ट करने के लिए एक स्वरूपित सूची में परिणाम देगा (यदि कम से कम 200000 अक्षर)।

जब से मैं इंस्टेंस के बीच स्विच कर रहा हूं, मैंने USE को जोड़ा।

USE PES
SELECT SUBSTRING(
    (SELECT ', ' + QUOTENAME(COLUMN_NAME)
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'Provider'
        ORDER BY ORDINAL_POSITION
        FOR XML path('')),
    3,
    200000);

3
SET IDENTITY_INSERT tableA ON

INSERT Into tableA ([id], [c2], [c3], [c4], [c5] ) 
SELECT [id], [c2], [c3], [c4], [c5] FROM tableB

इस तरह नहीं

INSERT INTO tableA
SELECT * FROM tableB

SET IDENTITY_INSERT tableA OFF

2

यह कोड स्निपेट दिखाता है कि प्राथमिक कुंजी स्तंभ चालू होने पर पहचान तालिका में कैसे सम्मिलित किया जाए।

SET IDENTITY_INSERT [dbo].[Roles] ON
GO
insert into Roles (Id,Name) values(1,'Admin')
GO
insert into Roles (Id,Name) values(2,'User')
GO
SET IDENTITY_INSERT [dbo].[Roles] OFF
GO

1

यदि आप किसी संग्रहीत कार्यविधि के माध्यम से अपने मानों को एक तालिका से दूसरी तालिका में सम्मिलित करना चाहते हैं। मैं प्रयोग किया जाता है इस और इस बाद जो लगभग Andomar के जवाब की तरह है,।

CREATE procedure [dbo].[RealTableMergeFromTemp]
    with execute as owner
AS
BEGIN
BEGIN TRANSACTION RealTableDataMerge
SET XACT_ABORT ON

    DECLARE @columnNameList nvarchar(MAX) =
     STUFF((select ',' + a.name
      from sys.all_columns a
      join sys.tables t on a.object_id = t.object_id 
       where t.object_id = object_id('[dbo].[RealTable]') 
    order by a.column_id
    for xml path ('')
    ),1,1,'')

    DECLARE @SQLCMD nvarchar(MAX) =N'INSERT INTO [dbo].[RealTable] (' + @columnNameList + N') SELECT * FROM [#Temp]'

    SET IDENTITY_INSERT [dbo].[RealTable] ON;
    exec(@sqlcmd)
    SET IDENTITY_INSERT [dbo].[RealTable] OFF

COMMIT TRANSACTION RealTableDataMerge
END

GO

0

एक या एक से अधिक स्तंभ हैं जिनके पास ऑटो-इन्क्रीमेंट प्रॉपर्टी है या उस विशेषता के मान की गणना बाधाओं के रूप में की जाएगी। आप उस कॉलम को संशोधित करने का प्रयास कर रहे हैं।

इसे हल करने के दो तरीके हैं 1) अन्य स्तंभों को स्पष्ट रूप से उल्लेख करें और केवल उनके मान सेट करें और प्राथमिककेय या ऑटो-इंक्रीमेंट कॉलम मान स्वचालित रूप से सेट हो जाएगा।

2) आप INDENTITY_INSERT को चालू कर सकते हैं और फिर अपनी प्रविष्टि क्वेरी निष्पादित कर सकते हैं अंत में IDENTITY_INSERT को बंद कर सकते हैं।

सुझाव: पहले चरण का पालन करें क्योंकि यह अधिक उपयुक्त और कुशल दृष्टिकोण है।

अधिक जानकारी के लिए इस लेख को SQL- हेल्पर पर पढ़ें ।


0

कृपया सुनिश्चित करें कि जिस तालिका से आप रिकॉर्ड का चयन कर रहे हैं, उस कॉलम के नाम, डेटा प्रकार और क्रम गंतव्य तालिका के समान ही हैं। केवल अंतर यह होना चाहिए कि गंतव्य तालिका में पहले स्तंभ के रूप में एक पहचान स्तंभ है, जो कि स्रोत तालिका में नहीं है।

जब मैं "INSERT INTO table_Dest SELECT * FROM table_source_linked_server_excel" निष्पादित कर रहा था, तो मैं इसी तरह के मुद्दे का सामना कर रहा था। तालिकाओं में 115 कॉलम थे।

मेरे पास दो ऐसी तालिकाएँ थीं जहाँ मैं डेटाबेस में एक्सेल (लिंक सर्वर के रूप में) से डेटा लोड कर रहा था। डेटाबेस तालिकाओं में, मैंने 'id' नामक एक पहचान कॉलम जोड़ा था जो कि स्रोत एक्सेल में नहीं था। एक तालिका के लिए क्वेरी सफलतापूर्वक चल रही थी और दूसरे में मुझे त्रुटि मिली "तालिका में पहचान स्तंभ के लिए एक स्पष्ट मूल्य केवल तब निर्दिष्ट किया जा सकता है जब एक स्तंभ सूची का उपयोग किया जाता है और IDENTITY_INSERT चालू SQL सर्वर है"। यह हैरान करने वाला था क्योंकि दोनों प्रश्नों के लिए परिदृश्य बिल्कुल समान था। इसलिए मैंने इसकी जांच की और मैंने पाया कि उस प्रश्न में जहां मुझे INSERT INTO .. ​​के साथ त्रुटि हो रही थी .. का चयन करें:

  1. स्रोत तालिका में कुछ स्तंभ नाम संशोधित किए गए थे, हालांकि मान सही थे
  2. वास्तविक डेटा कॉलमों से परे कुछ अतिरिक्त कॉलम थे जो सेलेक्ट * द्वारा चुने जा रहे थे। मैंने स्रोत एक्सेल टेबल (लिंक्ड सर्वर के तहत) पर "स्क्रिप्ट तालिका के रूप में> चयन करें> नई क्वेरी विंडो" के विकल्प का उपयोग करके यह पता लगाया। एक्सेल में आखिरी कॉलम के ठीक बाद एक छिपा हुआ कॉलम था, हालांकि इसमें कोई डेटा नहीं था। मैंने स्रोत Excel तालिका में उस स्तंभ को हटा दिया और उसे सहेज लिया।

उपरोक्त दो बदलाव करने के बाद INSERT INTO ... SELECT * के लिए क्वेरी सफलतापूर्वक चलाई गई। गंतव्य तालिका में पहचान स्तंभ अपेक्षित रूप से प्रत्येक सम्मिलित पंक्ति के लिए पहचान मान उत्पन्न करता है।

इसलिए, भले ही गंतव्य तालिका में कोई पहचान स्तंभ हो जो स्रोत तालिका में नहीं है, INSERT INTO .. ​​SELECT * सफलतापूर्वक चलेगा यदि स्रोत और गंतव्य में नाम, डेटा प्रकार और स्तंभ क्रम बिल्कुल समान हों।

आशा है कि यह किसी की मदद करता है।


-1

मुझे लगता है कि यह त्रुटि तालिका परिभाषा में स्तंभों की संख्या और सम्मिलित क्वेरी में स्तंभों की संख्या के साथ बेमेल होने के कारण होती है। साथ ही कॉलम की लंबाई दर्ज मूल्य के साथ छोड़ी गई है। तो बस इस समस्या को हल करने के लिए तालिका परिभाषा की समीक्षा करें


मेरे लिए काम किया: मैं डिजाइन से तालिका में एक कॉलम जोड़ना भूल गया, अच्छी बात यह है कि दूसरे उत्तरों की कोशिश करने से पहले इस बात की जांच करें।
गमबोआ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.