2008-10-09 16 views
13

मुझे एक फ़ंक्शन चाहिए जो किसी डेटाबेस पर INSERT कथन निष्पादित करता है और Auto_Increment प्राथमिक कुंजी देता है। मेरे पास निम्नलिखित सी # कोड है, लेकिन INSERT कथन ठीक काम करता है (मैं डेटाबेस में रिकॉर्ड देख सकता हूं, पीके सही ढंग से उत्पन्न होता है और पंक्तियां == 1), आईडी मान हमेशा होता है 0. क्या हो सकता है पर कोई विचार गलत?@@ INSERT कथन के बाद पहचान 0

public int ExecuteInsertStatement(string statement) 
    { 
     InitializeAndOpenConnection(); 
     int id = -1; 


     IDbCommand cmdInsert = connection.CreateCommand(); 
     cmdInsert.CommandText = statement; 
     int rows = cmdInsert.ExecuteNonQuery(); 

     if (rows == 1) 
     { 
      IDbCommand cmdId = connection.CreateCommand(); 
      cmdId.CommandText = "SELECT @@Identity;"; 
      id = (int)cmdId.ExecuteScalar(); 
     } 

     return id; 
    } 
    private void InitializeAndOpenConnection() 
    { 
     if (connection == null) 
      connection = OleDbProviderFactory.Instance.CreateConnection(connectString); 

     if(connection.State != ConnectionState.Open)     
      connection.Open(); 
    } 

जवाब के जवाब में, मैंने कोशिश की:

public int ExecuteInsertStatement(string statement, string tableName) 
    { 
     InitializeAndOpenConnection(); 
     int id = -1; 
     IDbCommand cmdInsert = connection.CreateCommand(); 
     cmdInsert.CommandText = statement + ";SELECT OID FROM " + tableName + " WHERE OID = SCOPE_IDENTITY();"; 
     id = (int)cmdInsert.ExecuteScalar(); 

     return id; 
    } 

लेकिन अब मैं

मैं एक एमएस एक्सेस उपयोग कर रहा हूँ "SQL विवरण के अंत के बाद पाया वर्ण" त्रुटि मिल रही है ओलेडीबी कनेक्शन के साथ डेटाबेस, प्रदाता = माइक्रोसॉफ्ट.जेट.ओएलडीबी 4.0

+0

आप क्या डेटाबेस सर्वर का उपयोग कर रहे स्पष्ट और संभवतः InitializeAndOpenConnection/connection.CreateCommand के लिए संदर्भ इनलाइन सकता है के रूप में वे करने के लिए हमारे जवाब को प्रभावित कर सकता आप? :) – Rob

+0

इसके अलावा - "ओआईडी = SCOPE_IDENTITY()" थिंक से पूरी "चयन ओआईडी कुछ हद तक जटिल है जैसा कि आप कह रहे हैं (3 के पहचान मान के साथ रिकॉर्ड किए गए रिकॉर्ड के लिए):" table_x से 3 चुनें 3 कहां = 3 "- थोड़े अनावश्यक – Rob

+0

@ रोब: यह अनावश्यक प्रतीत हो सकता है, लेकिन ओआईडी टाइप किया गया int है, जहां scope_identity() नहीं है, इसलिए आप सीधे (int) cmd.ExecuteScalar() – devio

उत्तर

1

मुझे लगता है कि आपको पहले निर्माण कमांड के साथ चयन @@ पहचान होना चाहिए - इसे "; SELECT @@ पहचान" और .xecuteScalar के माध्यम से इसे जोड़ने का प्रयास करेंसम्मिलन कथन

0

क्या आपकी तालिका पर कोई ट्रिगर्स है जो अन्य तालिकाओं में डाला जा सकता है? आम तौर पर हमें IDENT_CURRENT के पक्ष में @@ पहचान का उपयोग करने की सलाह दी जाती है ताकि आप गारंटी दे सकें कि वापस लौटाई गई तालिका उस तालिका के लिए है जिसे आपने अभी डाला है।

+1

मुझे लगता है कि आपको SCOPE_IDENTITY का उपयोग करना चाहिए क्योंकि यह वर्तमान सत्र में किसी भी तालिका के लिए उत्पन्न अंतिम पहचान मान देता है और वर्तमान दायरा इसलिए यदि आपको तालिका में सम्मिलित करने के बाद ही कहा जाता है तो आपको उचित मूल्य प्राप्त करने की गारंटी दी जाती है। – kristof

+0

IDENT_CURRENT के साथ हालांकि आप तालिका का नाम निर्दिष्ट करते हैं, आप गारंटी नहीं देते हैं कि यह आपके ऑपरेशन के दायरे में है, परिभाषा देखें: "निर्दिष्ट तालिका या दृश्य के लिए जेनरेट किया गया अंतिम पहचान मान देता है। अंतिम पहचान मान किसी भी सत्र के लिए हो सकता है और किसी भी दायरे " – kristof

+0

मुझे लगता है कि या तो इसकी कमी है। एक ही तालिका से "दूसरी" पहचान प्राप्त करने की संभावना एक ही दायरे में किसी अन्य तालिका से पहचान प्राप्त करने के समान होगी। या तो @@ पहचान से बेहतर है। –

0

मुझे लगता है कि @@ पहचान केवल आदेश के दायरे में मान्य है - आपके मामले में जब आप "कथन" निष्पादित करते हैं।

अपने "कथन" को संशोधित करें ताकि संग्रहीत प्रक्रिया स्वयं INSERT कथन के बाद @@ पहचान मूल्य वापस कर दे और संग्रहीत प्रक्रिया निष्पादन के रिटर्न कोड के रूप में इसे पढ़ सके। ","

15

1) (का उपयोग कर जोड़ सम्मिलित करें और SELECT कथन गठबंधन) 1 db आदेश में

2) SCOPE_IDENTITY (का उपयोग करें) @@ पहचान

सम्मिलित blabla जांच ... के बजाय; तालिका से चयन OID कहां OID = SCOPE_IDENTITY()

- अद्यतन:

के रूप में यह पता चला कि प्रश्न एमएस पहुंच से संबंधित था, मैं this article जिससे पता चलता है कि बस पहले आदेश पुन: उपयोग और उसके CommandText की स्थापना पाया "SELECT @@ पहचान" के लिए पर्याप्त होना चाहिए।

+0

कारण यह है कि अन्यथा आप दो आदेश जारी कर रहे हैं, और दूसरा आदेश पहले कमांड के बारे में ज़िलच जानता है और इसलिए जब आपने पहचान मान बनाया है तो आप उसे दूसरे (डिस्कनेक्ट) कमांड से बाहर नहीं निकाल रहे हैं। –

+0

यह मुझे "SQL कथन के अंत के बाद मिले वर्ण" त्रुटि देता है त्रुटि – Gillian

+0

पहले कथन के बाद बस "SELECT SCOPE_IDENTITY()" का उपयोग करें। इस के एक अच्छे स्पष्टीकरण के लिए नीचे मेरा लिंक देखें। – evilhomer

-1

जब आप एक्सेस का उपयोग कर रहे हैं, तो this article को एस्फाक से देखें, पृष्ठ के नीचे आधे रास्ते तक नीचे स्क्रॉल करें। कोड क्लासिक एएसपी में है, लेकिन उम्मीद है कि सिद्धांतों को अभी भी खड़ा होना चाहिए।


SELECT @@ पहचान को अलग निष्पादन संदर्भ के रूप में माना जा रहा है, मुझे विश्वास है। कोड है कि काम किया जाएगा चाहिए:

public int ExecuteInsertStatement(string statement) 
{ 
    InitializeAndOpenConnection(); 

    IDbCommand cmdInsert = connection.CreateCommand(); 
    cmdInsert.CommandText = statement + "; SELECT @@Identity"; 
    object result = cmdInsert.ExecuteScalar(); 

    if (object == DBNull.Value) 
    { 
     return -1; 
    } 
    else 
    { 
     return Convert.ToInt32(result); 
    } 
} 

आप शायद चाहते हैं/संयोजन है कि हालांकि 'का चयन @@ पहचान' कोड के अंत पर कहते हैं को साफ़ रखने की जरूरत है।

4

आपको प्रारंभिक कनेक्शन खोलने के साथ ही उसी समय पहचान वापस करने की आवश्यकता है। अपने डालने या आउटपुट चर से परिणाम सेट करें।

आपको हमेशा SCOPE_IDENTITY() नहीं @@ पहचान का उपयोग करना चाहिए।Reference here

आप डालने के बाद

SELECT SCOPE_IDENTITY() 

जोड़ना चाहिए।

+2

-1 एक्सेस डेटाबेस में नहीं। – Fionnuala

0

अपनी डेटाबेस सेटिंग्स की जांच करें। मुझे थोड़ी देर पहले एक ही समस्या थी और पता चला कि SQL सर्वर कनेक्शन सेटिंग 'कोई गिनती' सक्षम नहीं थी।

SQL सर्वर प्रबंधन स्टूडियो में, आप ऑब्जेक्ट एक्सप्लोरर में सर्वर पर राइट-क्लिक करके इसे ढूंढ सकते हैं, गुणों का चयन कर सकते हैं और फिर कनेक्शन पृष्ठ पर नेविगेट कर सकते हैं। "डिफ़ॉल्ट कनेक्शन विकल्प" के लिए सेटिंग्स को देखें

+0

दोह, बस पढ़ें कि आप एमएस एक्सेस का उपयोग कर रहे थे, न कि SQL सर्वर। सुनिश्चित नहीं है कि मेरा उत्तर एमएस एक्सेस पर लागू होता है ... –

+0

एक्सेस का उपयोग नहीं कर रहा है, लेकिन जेट। –

4

आप जेट (SQL सर्वर नहीं) का उपयोग कर रहे हैं और जेट केवल एक कमांड कथन को एक कमांड में संभाल सकता है, इसलिए आपको एक अलग कमांड में SELECT @@IDENTITY निष्पादित करने की आवश्यकता है, जाहिर है कि यह सुनिश्चित करता है कि यह इसका उपयोग करता है INSERT के समान कनेक्शन।

0

क्या उत्तरदाताओं में से अधिकांश नहीं भूल रहे हैं कि पूछताछ SQL सर्वर का उपयोग नहीं कर रहा है?

जाहिर है, एमएस एक्सेस 2000 और बाद में doesn't support @@IDENTITY विकल्प "रोउडडेटेड ईवेंट का उपयोग करना है, आप यह निर्धारित कर सकते हैं कि कोई INSERT हुआ है, नवीनतम @@ पहचान मूल्य पुनर्प्राप्त करें, और डेटासेट में स्थानीय तालिका के पहचान कॉलम में रखें।"

और हाँ, यह एक्सेस डीबी में एम्बेडेड वीबीए के लिए है। यह एक्सेस ऑब्जेक्ट लाइब्रेरी के माध्यम से एक्सेस के बाहर अभी भी कॉल करने योग्य है।

संपादित करें: ठीक है, यह समर्थित है, जल्दी सुबह के जवाब के लिए खेद है। लेकिन बाकी का जवाब मदद कर सकता है।

+0

"एमएस एक्सेस 2000 और बाद में @@ पहचान का समर्थन नहीं करता है" - आपको यह गलत रास्ता मिल गया है। @@ पहचान केवल एमएस एक्सेस 2000 से समर्थित है। ओपी ने कहा कि वे जेट 4.0 का उपयोग कर रहे हैं, जिसे पहली बार एमएस एक्सेस 2000 के साथ भेज दिया गया था। – onedaywhen

+0

अधिकतर उत्तरकर्ता इसे भूल नहीं रहे हैं - तथ्य यह है कि लक्षित डेटाबेस इंजन एक्सेस था जब तक कि कुछ उचित उत्तर दिए जाने तक :) – Rob

+0

कहानी का नैतिक: 6 बजे सवालों का जवाब न दें – moffdub

7

माइक्रोसॉफ्ट.जेट.ओएलडीबी.4.0 प्रदाता जेट वी 3 और जेट वी 4 डेटाबेस इंजन का समर्थन करता है, हालांकि SELECT @@ पहचान जेट v3 के लिए समर्थित नहीं है।

एमएसएफ़ 97 9 जेट v3 है और SELECT @@ पहचान का समर्थन नहीं करता है; यह MSAccess 2000 और ऊपर समर्थित है।

+0

एक ही समस्या होने के बाद मैं एक ही निष्कर्ष पर आया हूं। अन्य उत्तरों में अन्य सभी "समाधान" बस एक्सेस/जेट पर लागू नहीं हैं। –

0

यदि आप डालने वाले लेन-देन की स्वत: चलती संख्या का मूल्य पुनर्प्राप्त करना चाहते हैं और के बाद आपका पर्यावरण पुनर्प्राप्त करना चाहते हैं 1. डेटाबेस एमएसएसीसी है। 2. ड्राइवर इस तरह कनेक्शन स्ट्रिंग के साथ Jet4 है "प्रदाता = Microsoft.Jet.OLEDB.4.0; पासवर्ड = {0}; डेटा स्रोत = {1}; भी बनी रहती सुरक्षा जानकारी = सच" 3. उपयोग OLEDB


1. दो आदेश प्रत्येक किसी एक क्वेरी को स्वीकार बनाएं: अपने कोड को

OleDbConnection connection = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Password={0};Data Source={1};Persist Security Info=True",dbinfo.Password,dbinfo.MsAccessDBFile); 
connection.Open(); 
OleDbTransaction transaction = null; 
try{ 
    connection.BeginTransaction(); 
    String commandInsert = "INSERT INTO TB_SAMPLE ([NAME]) VALUES ('MR. DUKE')"; 
    OleDbCommand cmd = new OleDbCommand(commandInsert , connection, transaction); 
    cmd.ExecuteNonQuery(); 
    String commandIndentity = "SELECT @@IDENTITY"; 
    cmd = new OleDbCommandcommandIndentity, connection, transaction); 
    Console.WriteLine("New Running No = {0}", (int)cmd.ExecuteScalar()); 
    connection.Commit(); 
}catch(Exception ex){ 
    connection.Rollback(); 
}finally{ 
    connection.Close(); 
} 
-2
CREATE procedure dbo.sp_whlogin 
(
@id nvarchar(20), 
@ps nvarchar(20), 
@curdate datetime, 
@expdate datetime 
) 

AS 
BEGIN 
DECLARE @role nvarchar(20) 
DECLARE @menu varchar(255) 
DECLARE @loginid int 

SELECT  @role = RoleID 
FROM   dbo.TblUsers 
WHERE UserID = @id AND UserPass = @ps 

if @role is not null 
BEGIN 
    INSERT INTO TblLoginLog (UserID, LoginAt, ExpireAt, IsLogin) VALUES (@id, @curdate, @expdate, 1); 
    SELECT @loginid = @@IDENTITY; 
    SELECT @loginid as loginid, RoleName as role, RoleMenu as menu FROM TblUserRoles WHERE RoleName = @role 
END 
else 
BEGIN 
    SELECT '' as role, '' as menu 
END 
END 
GO 
+0

-1 डेटाबेस जेट/एसीई है। – Fionnuala

0

संक्षिप्त उत्तर मेरी उदाहरण आवेदन कर सकते हैं।
2. प्रथम एसक्यूएल क्वेरी आईएनएसईआरटी रिकॉर्ड है।
3. दूसरी एसक्यूएल क्वेरी "SELECT @@ पहचान है;" जो ऑटो नम्बर लौटाता है।
4. cmd.ExecuteScalar() का उपयोग करें जो पहली पंक्ति का पहला स्तंभ देता है।
5. लौटा परिणाम आउटपुट वर्तमान सम्मिलित क्वेरी में उत्पन्न ऑटो नम्बर मान है।

It is referenced from this link। उदाहरण कोड नीचे है। "समान कनेक्शन वीएस नया कनेक्शन" के लिए अंतर नोट करें। वही कनेक्शन वांछित आउटपुट देता है।

class Program 
{ 
    static string path = @"<your path>"; 
    static string db = @"Test.mdb"; 
    static void Main(string[] args) 
    { 
     string cs = String.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}\{1}", path, db); 
     // Using the same connection for the insert and the SELECT @@IDENTITY 
     using (OleDbConnection con = new OleDbConnection(cs)) 
     { 
      con.Open(); 
      OleDbCommand cmd = con.CreateCommand(); 
      for (int i = 0; i < 3; i++) 
      { 
       cmd.CommandText = "INSERT INTO TestTable(OurTxt) VALUES ('" + i.ToString() + "')"; 
       cmd.ExecuteNonQuery(); 

       cmd.CommandText = "SELECT @@IDENTITY"; 
       Console.WriteLine("AutoNumber: {0}", (int)cmd.ExecuteScalar()); 
      } 
      con.Close(); 
     } 
     // Using a new connection and then SELECT @@IDENTITY 
     using (OleDbConnection con = new OleDbConnection(cs)) 
     { 
      con.Open(); 
      OleDbCommand cmd = con.CreateCommand(); 
      cmd.CommandText = "SELECT @@IDENTITY"; 
      Console.WriteLine("\nNew connection, AutoNumber: {0}", (int)cmd.ExecuteScalar()); 
      con.Close(); 
     } 
    } 
} 

यह आत्म व्याख्यात्मक उत्पादन का उत्पादन करना चाहिए:

AutoNumber: 1 <br> 
AutoNumber: 2 <br> 
AutoNumber: 3 <br> 

New connection, AutoNumber: 0 
संबंधित मुद्दे