سؤال

لدي عبارة SQL ديناميكية قمت بإنشائها في إجراء مخزن.أحتاج إلى تكرار النتائج باستخدام المؤشر.أواجه صعوبة في معرفة بناء الجملة الصحيح.هذا ما أفعله.

SELECT @SQLStatement = 'SELECT userId FROM users'

DECLARE @UserId

DECLARE users_cursor CURSOR FOR
EXECUTE @SQLStatment --Fails here. Doesn't like this

OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @UserId

WHILE @@FETCH_STATUS = 0
BEGIN

EXEC asp_DoSomethingStoredProc @UserId

END
CLOSE users_cursor
DEALLOCATE users_cursor

ما هي الطريقة الصحيحة للقيام بذلك؟

هل كانت مفيدة؟

المحلول

وA المؤشر لن يقبل إلا بيانا حدد، لذلك إذا كان SQL تحتاج حقا أن تكون ديناميكية جعل جزء تعلن المؤشر البيان يتم تنفيذ. لأدناه للعمل الخادم الخاص بك سيكون لديك لتكون باستخدام المؤشرات العالمية.

Declare @UserID varchar(100)
declare @sqlstatement nvarchar(4000)
--move declare cursor into sql to be executed
set @sqlstatement = 'Declare  users_cursor CURSOR FOR SELECT userId FROM users'

exec sp_executesql @sqlstatement


OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @UserId

WHILE @@FETCH_STATUS = 0
BEGIN
Print @UserID
EXEC asp_DoSomethingStoredProc @UserId

FETCH NEXT FROM users_cursor --have to fetch again within loop
INTO @UserId

END
CLOSE users_cursor
DEALLOCATE users_cursor

إذا كنت بحاجة إلى تجنب استخدام المؤشرات العالمية، التي يمكن أيضا إدراج نتائج SQL ديناميكي في جدول مؤقت، ومن ثم استخدام هذا الجدول لتعبئة المؤشر.

Declare @UserID varchar(100)
create table #users (UserID varchar(100))

declare @sqlstatement nvarchar(4000)
set @sqlstatement = 'Insert into #users (userID) SELECT userId FROM users'
exec(@sqlstatement)

declare users_cursor cursor for Select UserId from #Users
OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @UserId

WHILE @@FETCH_STATUS = 0
BEGIN

EXEC asp_DoSomethingStoredProc @UserId

FETCH NEXT FROM users_cursor
INTO @UserId

END
CLOSE users_cursor
DEALLOCATE users_cursor

drop table #users

نصائح أخرى

وهذا الرمز هو مثال جيد جدا لعمود ديناميكية مع المؤشر، لأنك لا تستطيع استخدام '+' فيSTATEMENT:

ALTER PROCEDURE dbo.spTEST
AS
    SET NOCOUNT ON
    DECLARE @query NVARCHAR(4000) = N'' --DATA FILTER
    DECLARE @inputList NVARCHAR(4000) = ''
    DECLARE @field sysname = '' --COLUMN NAME
    DECLARE @my_cur CURSOR
    EXECUTE SP_EXECUTESQL
        N'SET @my_cur = CURSOR FAST_FORWARD FOR
            SELECT
                CASE @field
                    WHEN ''fn'' then fn
                    WHEN ''n_family_name'' then n_family_name
                END
            FROM
                dbo.vCard
            WHERE
                CASE @field
                    WHEN ''fn'' then fn
                    WHEN ''n_family_name'' then n_family_name
                END
                LIKE ''%''+@query+''%'';
            OPEN @my_cur;',
        N'@field sysname, @query NVARCHAR(4000), @my_cur CURSOR OUTPUT',
        @field = @field,
        @query = @query,
        @my_cur = @my_cur OUTPUT
    FETCH NEXT FROM @my_cur INTO @inputList
    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT @inputList
        FETCH NEXT FROM @my_cur INTO @inputList
    END
    RETURN

العمل مع قاعدة بيانات غير العلائقية (IDMS أي شخص؟) عبر اتصال ODBC يوصف بأنه واحد من تلك الأوقات حيث المؤشرات وSQL ديناميكية يبدو أن الطريق الوحيد.

select * from a where a=1 and b in (1,2)

ويأخذ 45 دقيقة للرد بينما أعيدت كتابتها لاستخدام keysets دون في البند سيتم تشغيل في أقل من 1 ثانية:

select * from a where (a=1 and b=1)
union all
select * from a where (a=1 and b=2)

وإذا كان في بيان للعمود B يحتوي على 1145 الصفوف، وذلك باستخدام المؤشر إلى إنشاء عبارات indidivudal وتنفيذها كما SQL الديناميكي هو أسرع بكثير من استخدام في البند. سخيفة يا؟

ونعم، ليس هناك وقت في قاعدة بيانات علائقية التي يجب أن تستخدم في المؤشر. أنا فقط لا يمكن أن أصدق أنني قد وصلنا عبر مثيل حيث حلقة المؤشر هي عدة مقادير أسرع.

أولا، تجنب استخدام المؤشر إذا كان ذلك ممكنا. وفيما يلي بعض الموارد لاستئصال بها عندما يبدو أنك لا يمكن الاستغناء عنها:

يجب أن يكون هناك 15 طرق لانقاص والمؤشرات الخاصة بك ... جزء 1، مقدمة

تجهيز صف على حدة الصف بدون المؤشر

وقال ذلك، على الرغم من أنك قد تكون عالقة مع واحدة بعد كل شيء - أنا لا أعرف ما يكفي من سؤالك للتأكد من أن أي من تلك تطبيق. إذا كان هذا هو الحال، كنت قد حصلت مشكلة مختلفة - يجب أن تكون العبارة حدد المؤشر لعلامة <م> الفعلي عبارة SELECT، وليس عبارة EXECUTE. كنت عالقا.

ولكن انظر جواب من cmsjr (والذي جاء في حين كنت أكتب) حول استخدام جدول مؤقت. وأود أن تجنب العالمي المؤشرات أكثر من "سهل" منها ....

بعد التبديل مؤخرًا من Oracle إلى SQL Server (تفضيل صاحب العمل)، لاحظت أن دعم المؤشر في SQL Server متأخر.المؤشرات ليست دائما شريرة، وأحيانا تكون مطلوبة، وأحيانا أسرع بكثير، وأحيانا أكثر نظافة من محاولة ضبط استعلام معقد عن طريق إعادة ترتيب أو إضافة تلميحات التحسين.يعتبر الرأي "المؤشرات شريرة" أكثر بروزًا في مجتمع SQL Server.

لذلك أعتقد أن هذه الإجابة هي التبديل إلى Oracle أو إعطاء MS دليلاً.

وهناك مثال آخر وهو أود أن أشاطركم صور: D http://www.sommarskog.se/dynamic_sql.html#cursor0

وثمة خيار آخر في SQL Server هو أن تفعل كل الاستعلام عن الدينامية الخاصة بك إلى متغير جدول في بروك المخزنة، ثم استخدام مؤشر الاستعلام ومعالجة ذلك. كما أن النقاش المؤشر اللعين :)، لقد رأيت دراسات تبين أن في بعض الحالات، مؤشر يمكن أن يكون في الواقع أسرع إذا صحيح إعداد. أنا استخدامها نفسي عندما الاستعلام المطلوب هو معقد جدا، أو فقط لا إنسانيا (بالنسبة لي؛).) ممكن

وهذا الرمز يمكن أن تكون مفيدة بالنسبة لك.

ومثال على استخدام المؤشر في خادم SQL

DECLARE sampleCursor CURSOR FOR 
      SELECT K.Id FROM TableA K WHERE ....;
OPEN sampleCursor
FETCH NEXT FROM sampleCursor INTO @Id
WHILE @@FETCH_STATUS <> -1
BEGIN

UPDATE TableB
   SET 
      ...
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top