Creating your own sp_MSforeach stored procedure

  • Brian Knight

    One Orange Chip

    Points: 27249

    Comments posted to this topic are about the content posted at http://www.sqlservercentral.com/columnists/bknight/sp_msforeachworker.asp

  • Simon Burke

    SSC Rookie

    Points: 33

    Hi Brian,

    In trying to run the MSforEachTrigger script in 2005 I'm getting errors - any idea what's going on??

    Thanks, Simon

    Msg 16950, Level 16, State 2, Procedure sp_MSforeach_worker, Line 27

    The variable '@local_cursor' does not currently have a cursor allocated to it.

    Msg 16950, Level 16, State 2, Procedure sp_MSforeach_worker, Line 32

    The variable '@local_cursor' does not currently have a cursor allocated to it.

    Msg 16950, Level 16, State 2, Procedure sp_MSforeach_worker, Line 153

    The variable '@local_cursor' does not currently have a cursor allocated to it.

    Msg 16916, Level 16, State 1, Procedure sp_MSforeach_worker, Line 155

    A cursor with the name 'hCForEachDatabase' does not exist.

  • homebrew01

    SSC Guru

    Points: 55137

    And the 4 "foreach" links at the bottom of the page are dead.

  • Fred McConville

    SSC Veteran

    Points: 227

    Just came across the error myself.

    Msg 16950, Level 16, State 2, Procedure sp_MSforeach_worker, Line 31

    The variable '@local_cursor' does not currently have a cursor allocated to it.

    The statement has been terminated.

    The sp's [sp_MSforeachtable] and [sp_MSforeach_worker] have been changed, for a start they now belong to the sys schema (no longer prefixed dbo, but I think SQL finds the sys schema copy anyway) and the cursor sp_MSforeachtable uses when it calls sp_MSforeach_worker is "hCForEachTable" (or "hCForEachDatabase" for databases) instead of "hCForEach". They've also added another variable to distinguish for each database and each table. The error message you get is because the new cursor name doesn't match the old name (which is in the sp's in the original article).

    Just follow the original instructions to alter the current sp_MSforeachtable to create the new ones, you could try fixing the originals but easier to start again.

    Cheers

    Fred

  • rockfordphile

    SSC Veteran

    Points: 210

    Just had a go at this myself, ran into some errors, thought I'd post what needed to be done for SQL 2008 R2 to hopefully help the next guy get through it a bit faster.

    The key, as mentioned above, is the changed procedure. After that, it's important to change SET QUOTED IDENTIFIER OFF - not ON, as in the original article code[/url]. Took me a minute (and a helpful blog from a fellow in Romania) to get that. 🙂

    USE MASTER

    GO

    if exists (select name from sysobjects

    where name = 'sp_MSforeachview' AND type = 'P')

    drop procedure sp_MSforeachview

    GO

    SET QUOTED_IDENTIFIER OFF

    GO

    SET ANSI_NULLS ON

    GO

    create proc sp_MSforeachview

    @command1 nvarchar(2000), @replacechar nchar(1) = N'?', @command2 nvarchar(2000) = null,

    @command3 nvarchar(2000) = null, @whereand nvarchar(2000) = null,

    @precommand nvarchar(2000) = null, @postcommand nvarchar(2000) = null

    as

    /* This proc returns one or more rows for each table (optionally, matching @where), with each table defaulting to its own result set */

    /* @precommand and @postcommand may be used to force a single result set via a temp table. */

    /* Preprocessor won't replace within quotes so have to use str(). */

    declare @mscat nvarchar(12)

    select @mscat = ltrim(str(convert(int, 0x0002)))

    if (@precommand is not null)

    exec(@precommand)

    /* Create the select */

    exec(N'declare hCForEachTable cursor global for select ''['' + REPLACE(schema_name(syso.schema_id), N'']'', N'']]'') + '']'' + ''.'' + ''['' + REPLACE(object_name(o.id), N'']'', N'']]'') + '']'' from dbo.sysobjects o join sys.all_objects syso on o.id =

    syso.object_id '

    + N' where OBJECTPROPERTY(o.id, N''IsView'') = 1 ' + N' and o.category & ' + @mscat + N' = 0 '

    + @whereand)

    declare @retval int

    select @retval = @@error

    if (@retval = 0)

    exec @retval = sys.sp_MSforeach_worker @command1, @replacechar, @command2, @command3, 0

    if (@retval = 0 and @postcommand is not null)

    exec(@postcommand)

    return @retval

    GO

    SET ANSI_NULLS ON

    GO

  • RBarryYoung

    SSC Guru

    Points: 143327

    Here'e another way to do this: here[/url]

    [font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
    Proactive Performance Solutions, Inc.
    [/font]
    [font="Verdana"] "Performance is our middle name."[/font]

Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic. Login to reply