2011-06-06 12 views
7

मेरे पास डेटाबेस में अभिभावक-बाल संबंध हैं। मुझे क्या करना है माता-पिता की क्वेरी के माध्यम से लूप है, और माता-पिता की प्राथमिक कुंजी का उपयोग करके, अपने बच्चों को मिल गया। मेरे पास यह मुद्दा है कि ऐसा करने के लिए मुझे पैरामीटरयुक्त कर्सर (कुंजी में पास) का उपयोग करने की आवश्यकता है।क्या SQL सर्वर कर्सर में पैरामीटर का उपयोग करने का कोई तरीका है?

क्या एसक्यूएल सर्वर में ऐसी कोई चीज है या इस पर नकल करने की चाल है? मैं यह कर की कोशिश की, लेकिन यह काम नहीं किया:

DECLARE @value VARCHAR(20); 
DECLARE @someKey NUMERIC(19,0); 

DECLARE main_curs 
CURSOR FOR SELECT value FROM someTable where key = @someKey; 

SET @someKey = 12345; 

OPEN main_curs 
FETCH NEXT FROM main_curs INTO @value; 
CLOSE main_curs 
DEALLOCATE main_curs 

लेकिन ऐसा लगता है कि यह मेरे @someKey की स्थापना लेने नहीं करता है।

इस पर किसी भी मदद की सराहना की जाएगी। धन्यवाद!

अद्यतन

मैं के रूप में मैं उदाहरण बना अधिक जानकारी शामिल करना चाहिए बहुत आसान लग रहे हैं। मेरे पास एकाधिक @ सोमेकी मान हैं जिन्हें मुझे उपयोग करने की आवश्यकता है। जैसा कि पहले उल्लेख किया गया है, मेरे माता-पिता के रिश्ते हैं और मेरे पास 6 बच्चे हो सकते हैं। तो मुझे माता-पिता और उसके संबंधित कॉलम की सूची मिल रही है और इसके माध्यम से पुनरावृत्ति हो रही है। WHILE-LOOP में, मैं माता-पिता से प्राथमिक कुंजी प्राप्त करना चाहता था और बच्चे की जानकारी प्राप्त करने के लिए एक और कर्सर को कॉल करना चाहता था (विभिन्न कॉलम लौटा)। तो मैं अलग-अलग @someKey मान सेट के साथ बाल कर्सर को कई कॉल करता। उम्मीद है कि समझ में आता है।

+0

क्या आप सिर्फ डेटा के लिए पूछ सकते हैं और चयन का उपयोग नहीं करते हैं, यह आमतौर पर अधिक कुशल है? – Mark

उत्तर

0

एक चीज जिसे आप कोशिश कर सकते हैं nested cursors का उपयोग कर रहा है। इसका एक उदाहरण शीर्षक पृष्ठ के नीचे है: रिपोर्ट आउटपुट उत्पन्न करने के लिए नेस्टेड कर्सर का उपयोग करना।

0

इससे पहले कि आप @someKey = 12345; निर्धारित करने की आवश्यकता कर्सर घोषणा जैसे:

SET @someKey = 12345; 
DECLARE main_curs 
CURSOR FOR SELECT value FROM someTable where key = @someKey; 
+0

मैंने यह कोशिश की और पाया कि कर्सर की सामग्री बदलती नहीं है अगर आप कर्सर बंद करते हैं, चर में मान बदलते हैं, और फिर कर्सर को फिर से खोलें। ऐसा प्रतीत होता है कि कर्सर परिभाषा DECLARE कथन में "संकलित" है। मैं यहाँ कर्सर को फिर से चलाने के लिए काम के आसपास एक काम की तलाश में आया था। –

0

आप कोई बात बिगड़ के आदेश है लगता है, और आप वास्तव में कर्सर के अंदर कुछ भी करने से नहीं कर रहे हैं?

DECLARE @value VARCHAR(20); 
DECLARE @someKey NUMERIC(19,0); 

SET @someKey = 12345; --this has to be set before its used in cursor declaration 

DECLARE main_curs 
CURSOR FOR SELECT value FROM someTable where key = @someKey; 
OPEN main_curs 
FETCH NEXT FROM main_curs INTO @value;  -- first row is fetched 

WHILE @@FETCH_STATUS = 0  -- start the loop 
BEGIN 

-- do something here with @value 

FETCH NEXT FROM main_curs INTO @value; --fetch the next row 
END 

CLOSE main_curs 
DEALLOCATE main_curs 
0

यदि आप एक रिकर्सिव पदानुक्रम सीटीई का उपयोग करना चाहते हैं, तो Recursive Queries Using Common Table Expressions देखें।

create table test (
    id int not null identity(1,1) primary key, 
    parent_id int null, 
    data varchar (max)); 
go 

insert into test (parent_id, data) values 
    (null, 'root'), 
    (1, 'child 1'), 
    (1, 'child 2') , 
    (2, 'child of child 1'), 
    (4, 'child of child of child 1'); 
go 

declare @root int = 2; 

declare crs cursor for 
    with cte as (
     select id, parent_id, data 
     from test 
     where id = @root 
     union all 
     select t.id, t.parent_id, t.data 
     from test t 
      join cte c on t.parent_id = c.id) 
    select id, data from cte;  
open crs; 

declare @id int, @data varchar(max); 
fetch next from crs into @id, @data; 
while @@fetch_status = 0 
begin 
    print @data; 
    fetch next from crs into @id, @data; 
end 

close crs; 
deallocate crs; 

लेकिन सबसे अधिक बार पुनरावर्ती सीटीई पूरी तरह से एक कर्सर की आवश्यकता को समाप्त कर सकते हैं: आप पुनरावर्ती CTE पर अपने कर्सर, जैसे घोषणा कर सकते हैं।

4

आपको 2 कर्सर की आवश्यकता है - एक माता पिता के लिए और एक बच्चे के लिए। सुनिश्चित करें कि बच्चे के कर्सर को बाहर के अंदर नहीं भेजा गया है। अगर आप बाहर घोषित करते हैं तो यह काम नहीं करेगा।

जैसे:

DECLARE @value VARCHAR(20); 
DECLARE @someKey NUMERIC(19,0); 

DECLARE main_curs 
CURSOR FOR SELECT value FROM someTable where key = @someKey; 

SET @someKey = 12345; 

OPEN main_curs 
FETCH NEXT FROM main_curs INTO @value; 
while @@FETCH_STATUS = 0 
BEGIN 

DECLARE CHILD_CURS CURSOR FOR SELECT VALUE2 FROM CHILDTABLE WHERE [email protected]; 
open child_curs 
fetch next from child_curs into @x,@y 

close child_curs 
deallocate child_curs 

FETCH NEXT FROM main_curs INTO @value; 
END 

CLOSE main_curs 
DEALLOCATE main_curs 
+0

यह @ सोमेकी के एक ही मूल्य के लिए काम करता है, लेकिन जैसा कि कार्ल होग्लुंड इस समाधान के बारे में एक और उत्तर पर एक टिप्पणी में कहता है, "मैंने कोशिश की और पाया कि कर्सर को बंद करने पर कर्सर की सामग्री बदलती नहीं है, मान बदलें परिवर्तनीय में, और उसके बाद कर्सर को फिर से खोलें। ऐसा प्रतीत होता है कि कर्सर परिभाषा DECLARE कथन में "संकलित" है। मैं यहाँ कर्सर को फिर से चलाने के लिए काम के आसपास की तलाश में आया था। " जो हम में से तीन को उस उत्तर की तलाश में बनाता है, जिसमें ओपी में अपडेट के अनुसार एस्कलोनियन भी शामिल है। –

+0

@Rob - जॉन केन द्वारा पोस्ट किए गए नेस्टेड कर्सर पर माइक्रोसॉफ्ट हेल्प डॉक्यूमेंटेशन के लिंक में दी गई जानकारी के अनुसार, आपकी प्रतिक्रिया कुछ हद तक गलत है। हालांकि यह सच है कि बच्चे कर्सर को बंद करने से सामग्री में कोई बदलाव नहीं होता है, बच्चे कर्सर को हटाने से एसक्यूएल को लूप के अगले पुनरावृत्ति पर कर्सर को फिर से बनाने के लिए मजबूर करता है (और इस प्रकार सामग्री को बदलता है)। तो कार्ल भ्रामक है और साथ ही यह पोस्ट भ्रामक है। आप आंतरिक बच्चे कर्सर को लूप के भीतर इसे हटाकर अपेक्षित प्रदर्शन करने के लिए प्राप्त कर सकते हैं, न केवल इसे बंद कर सकते हैं। तो यह उदाहरण सटीक है। – Mitselplik

0

एक अन्य जगह में, किसी एक संग्रहीत प्रक्रिया (एक तदर्थ स्क्रिप्ट से एसक्यूएल संकलित बल्कि) का उपयोग का सुझाव दिया, लेकिन है कि या तो काम नहीं करता। यहाँ एक और मेगावाट कि इस मुद्दे को काफी स्पष्ट रूप से पता चलता है:

/* Should print: 
dbNamein=master dbNameout=master 
dbNamein=model dbNameout=model 
dbNamein=msdb dbNameout=msdb 
*/ 
create procedure [TestParamsWithOpenCursorStmt] 
as 
begin 

    declare @dbNameIn [nvarchar](255) = N'tempdb', 
     @dbNameOut [nvarchar](255), 
     @fs [int]; 
    declare dbNames cursor for 
     select db.[name] from [master].[sys].[databases] db 
     where db.[name] = @dbNameIn; 
    while (@dbNameIn != N'msdb') begin 
     if @dbNameIn = N'tempdb' 
     set @dbNameIn = N'master' 
     else if @dbNameIn = N'master' 
     set @dbNameIn = N'model' 
     else if @dbNameIn = N'model' 
     set @dbNameIn = N'msdb'; 
     open dbNames; 
     fetch next from dbNames into @dbNameOut; 
     set @fs = @@fetch_status; 
     if @fs != 0 continue; 
     raiserror (N'dbNamein=%s dbNameout=%s', 0, 0, @dbNameIn, @dbNameOut) with nowait; 
     close dbNames; 
    end; 
    deallocate dbNames; 

end; 
go 

execute [TestParamsWithOpenCursorStmt]; 

ऐसा लगता है कि चर (और समय में अपने मूल्य) के लिए "की घोषणा ... कर्सर" के बजाय खुला कर्सर बाध्य हो जाता है।

1

यहां 'EXEC()' फ़ंक्शन का उपयोग करके आप गतिशील एसक्यूएल के साथ एक कर्सर घोषित कर सकते हैं। आश्चर्य की बात यह काम करता है।उदाहरण के लिए:

DECLARE @QuotedDatabase NVARCHAR(128) = QUOTENAME('ReportServer') 
DECLARE @ObjectID INT = 389576426 
DECLARE @ColumnName NVARCHAR(128) 
DECLARE @ColumnType NVARCHAR(128) 
DECLARE @DeclareColumnCursor NVARCHAR(4000) 
SET @DeclareColumnCursor = ' 
    DECLARE ColumnCursor CURSOR READ_ONLY FORWARD_ONLY FOR 
    SELECT c.Name, t.Name 
    FROM ' + @QuotedDatabase + '.sys.columns c 
    INNER JOIN ' + @QuotedDatabase + '.sys.types t 
    ON c.user_type_id = t.user_type_id 
    WHERE c.object_id = ' + CAST(@ObjectID AS NVARCHAR) + ' 
    ORDER BY column_id' 
EXEC(@DeclareColumnCursor) 
OPEN ColumnCursor 
FETCH NEXT FROM ColumnCursor INTO @ColumnName, @ColumnType 
PRINT @ColumnName + ',' + @ColumnType 
CLOSE ColumnCursor 
DEALLOCATE ColumnCursor 
संबंधित मुद्दे

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