2010-04-26 24 views
6

के अंदर एक संग्रहित प्रो बनाएं, मेरे पास एक एसक्यूएल स्क्रिप्ट है जो उत्पादन में रोल करने के लिए सेट है। मैंने विभिन्न परियोजनाओं को अलग-अलग लेनदेन में लपेट लिया है। प्रत्येक लेनदेन में हमने संग्रहित प्रक्रियाएं बनाई हैं। मुझे त्रुटि संदेश मिल रहे हैंटीएसक्यूएल - एक लेनदेन कथन

संदेश 156, स्तर 15, राज्य 1, रेखा 4 कीवर्ड 'प्रक्रिया' के पास गलत वाक्यविन्यास।

मैं वर्णन करने के लिए

Begin Try 
Begin Transaction 
    -- do a bunch of add/alter tables here 
    -- do a bunch of data manipulation/population here 

    -- create a stored proc 
    create procedure dbo.test 
    as 
    begin 
    select * from some_table 
    end 
Commit 
End Try 
Begin Catch 
    Rollback 
    Declare @Msg nvarchar(max) 
    Select @Msg=Error_Message(); 
    RaisError('Error Occured: %s', 20, 101,@Msg) With Log; 
End Catch 

त्रुटि सूचित करते हैं कि मैं लेनदेन के अंदर संग्रहीत procs नहीं बना सकते लगता है इस उदाहरण स्क्रिप्ट बनाया है, लेकिन मैं किसी भी डॉक्स कि अन्यथा कहना नहीं मिल रहा हूँ (शायद isn गूगल आज स्वतंत्र रूप से नहीं है)।

+0

यह एसक्यूएल सर्वर के लिए है? –

+0

हां, क्षमा करें, मुझे इसका उल्लेख करना चाहिए था। एसक्यूएल 2008. –

+0

मैंने लेनदेन के निर्माण प्रक्रिया को खींचने का फैसला किया और अपने स्वयं के खंड में कोशिश/पकड़ लिया। मैंने "अगर मौजूद है तो ड्रॉप करें" कथन में डाल दिया है और संग्रहित प्रो निर्माण के आस-पास "यदि मौजूद है तो प्रिंट संदेश" स्टेटमेंट्स जोड़ा गया है। सभी प्रतिक्रियाओं के लिए धन्यवाद, मैंने इससे कुछ सीखा। –

उत्तर

10

कर EXEC('...') में create procedure, इस तरह की कोशिश:

Begin Try 
Begin Transaction 
    -- do a bunch of add/alter tables here 
    -- do a bunch of data manipulation/population here 

    -- create a stored proc 
    EXEC ('create procedure dbo.test 
    as 
    begin 
    select * from some_table 
    end') 
Commit 
End Try 
Begin Catch 
    Rollback 
    Declare @Msg nvarchar(max) 
    Select @Msg=Error_Message(); 
    RaisError('Error Occured: %s', 20, 101,@Msg) With Log; 
End Catch 

GO 
+3

+1। यह किया जाना चाहिए, क्योंकि 'प्रक्रिया बनाएं ...' कॉल को स्क्रिप्ट में पहला कथन होना चाहिए। इसे 'EXEC' के साथ अपने बैच में डालकर यह हल हो जाता है। इसका उपयोग स्क्रिप्ट फ़ाइलों को बनाने के लिए भी किया जा सकता है जो संग्रहीत प्रक्रिया को बनाते या अपडेट करते हैं। प्रक्रिया स्क्रिप्ट संग्रह के लिए बहुत उपयोगी है। –

+0

नमूना में, यदि आप इसे सीधे चलाते हैं (कुछ_table के लिए वास्तविक तालिका नाम डालते हैं) ddl/dml सामग्री के साथ त्रुटि अभी भी होती है, और फिर भी निर्माण प्रक्रिया पहला कथन है, या मैं गलतफहमी हूं। –

+0

कोड मेरे लिए ठीक चलाता है, मुझे यकीन नहीं है कि आप –

0

मुझे याद करने के लिए आप को बनाने, संशोधित करने या डेटाबेस स्कीमा ड्रॉप तरह बातें नहीं कर सकते लगता है संग्रहित प्रक्रियाओं — एक सौदे के अंदर (जैसे संरचनात्मक के बाद सहित वस्तुओं — परिवर्तन लेनदेन नहीं हैं: आप डेटा परिवर्तनों के साथ उन्हें वापस रोल नहीं कर सकते हैं)।

+1

मैंने अपने उत्तर से कोड का परीक्षण किया, यह न केवल संग्रहित प्रक्रिया बनाता है, लेकिन यदि आप कोड में रोलबैक को मजबूर करते हैं, तो यह इसे वापस भी रोल करेगा। –

+1

@ केएम: यह निश्चित रूप से SQL सर्वर के हाल के संस्करणों में बदल सकता है। – Richard

10

आप अपनी स्क्रिप्ट इस तरह से नहीं लिख सकते हैं क्योंकि कई बयान हैं जो अपने बैच में चलाना चाहिए। इसके बजाय, मैं कैसे लाल गेट के एसक्यूएल की तुलना करने के लिए कुछ समान कर की सिफारिश करेंगे इसकी स्क्रिप्ट बनाता है:

Set Xact_Abort On 
GO 
Begin Transaction 
GO 
If object_id('tempdb..#tmpErrors') is not null 
    Drop Table #tmpErrors 
GO 
Create Table #tmpErrors([Error] int not null) 
GO 
Create Procedure dbo.Test 
As 
Begin 
    --.... 
End 
GO 
If @@Error <> 0 AND @@TranCount >0 Rollback Transaction 
GO 
IF @@TranCount = 0 Begin Insert #tmpErrors (Error) Select 1 Begin Transaction End 
GO 

-- more statements 

GO 
If @@Error <> 0 AND @@TranCount >0 Rollback Transaction 
GO 
IF @@TranCount = 0 Begin Insert #tmpErrors (Error) Select 1 Begin Transaction End 
GO 

--..... 

IF NOT EXISTS(SELECT * FROM #tmpErrors) 
    BEGIN 
     PRINT 'The database update succeeded' 
     IF @@TRANCOUNT > 0 COMMIT TRANSACTION 
    END 
ELSE 
    BEGIN 
     PRINT 'The database update failed' 
     IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION 
    END 
GO 

DROP TABLE #tmpErrors 
GO 
+0

एसएसएमएस शिकायत करता है कि 'त्रुटि' '#tmpErrors (त्रुटि) में कोई कॉलम नहीं है, इसे 'आईडी' होना चाहिए (या 'तालिका #tmpErrors (आईडी int null नहीं)' होना चाहिए 'तालिका बनाना # tmpErrors (त्रुटि int null) '? –

+0

@ सैमहोल्डर - हाँ। यह मेरे भाग पर एक टाइपो है जिसे मैंने सही किया। अगर आप 'आईडी' के साथ जाते हैं, तो तालिका तालिका विवरण स्पष्ट रूप से 'आईडी' का उपयोग करना चाहिए। अगर आप' त्रुटि 'के साथ जाते हैं, तो उस तालिका के लिए बनाएँ तालिका विवरण को अद्यतन करने की आवश्यकता है। – Thomas

+0

स्पष्टीकरण के लिए धन्यवाद। मेरे द्वारा +1। महान उत्तर –

2

समाधान के.एम. द्वारा प्रस्तावित के साथ विभिन्न मुद्दों के होते हैं:

  • तो तुम क्या की सामग्री अपने EXEC() कॉल में डाल दिया गया है, अर्थात् गलत है (उदाहरण के लिए आप संग्रहीत प्रक्रिया के अंदर से एक गैर-मौजूद तालिका डालते हैं) कि त्रुटि बुलबुला नहीं होती है और लेनदेन वापस नहीं चलाया जाता है।

  • यदि आपके EXEC() कॉल में जो भी रखा गया है, उसकी सामग्री गलत है (उदाहरण के लिए आप संग्रहित प्रक्रिया के अंदर SELECTT के बजाय SELECTT डालते हैं), लेनदेन वापस लुढ़का हुआ लगता है लेकिन एक पूरी तरह से गुप्त त्रुटि बुलबुले :

    A transport-level error has occurred when receiving results from the server. (provider: TCP Provider, error: 0 - The specified network name is no longer available.) 
    

तो मैं कैसे एक सौदे के अंदर एक प्रक्रिया बनाने के लिए करने के लिए एक नुकसान में अभी भी कर रहा हूँ, लेकिन अभी भी लेन-देन और कोशिश पकड़ उपयोगी हो सकते है।

+0

माइल के उत्तर में कैच ब्लॉक का उपयोग करें: http://stackoverflow.com/questions/180075/executing-a-stored-procedure-inside -begin अंत-लेन-देन – knocte

संबंधित मुद्दे