0

I am trying to write a stored procedure in SQL Server which will:

  • Take a list of integers as input ( let's assume these integers are "profile_id")
  • pick up all the table names which has a column named as "profile_id" into a cursor
  • loop through the cursor and print the profile_id value when it matches one of them in the input list of params.

Now the problem is: I am executing the procedure like this:

EXEC dbo.de_dup '1234,2345';

and getting a syntax error when trying to execute the commented out line below (Please see the procedure):

set @id = (select profile_id from @tname where profile_id in @a_profile_id );

Questions:

  1. What would be the right way of executing and setting the value inside a cursor?
  2. What is way (in our case) to pass a list of integers to this procedure?

This is my procedure:

ALTER PROCEDURE dbo.de_dup
    (@a_profile_id nvarchar(MAX)) 
AS
    DECLARE @tname VARCHAR(max),
            @id int;

    DECLARE tables_cursor CURSOR FOR 
        SELECT 
            a.TABLE_CATALOG +'.'+a.TABLE_SCHEMA + '.'+ a.TABLE_NAME AS table_name
        FROM 
            JobApp.INFORMATION_SCHEMA.COLUMNS a
        LEFT OUTER JOIN 
            JobApp.INFORMATION_SCHEMA.VIEWS b ON a.TABLE_CATALOG = b.TABLE_CATALOG
                                              AND a.TABLE_SCHEMA = b.TABLE_SCHEMA
                                              AND a.TABLE_NAME = b.TABLE_NAME
        WHERE 
            a.COLUMN_NAME = 'profile_id'
        GROUP BY 
            a.TABLE_CATALOG, a.TABLE_SCHEMA, a.TABLE_NAME, a.COLUMN_NAME;

    OPEN tables_cursor;

    FETCH NEXT FROM tables_cursor INTO @tname;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT @a_profile_id ;
        PRINT @tname ;
        --set @id= (select profile_id from @tname where profile_id in @a_profile_id );
        --PRINT 'id : ' + @id;

        FETCH NEXT FROM tables_cursor INTO @tname;
    END;

    CLOSE tables_cursor;
    DEALLOCATE tables_cursor;
GO;

Please let me know should I provide more clarification. Thanks in advance.

5
  • The first question and s why do you want to use a Cursor. Commented Sep 4, 2020 at 19:51
  • This is simplest example that I provided that we would do with cursor. We will do much more complex thing with each table name Commented Sep 4, 2020 at 19:54
  • can you please post the error? when you want to execute a query where the table name is in a variable, you need to use the dynamic SQL concept Commented Sep 4, 2020 at 20:01
  • You want the profile id's to be just printed? what is the sql-server version? Commented Sep 4, 2020 at 20:04
  • we want to use incoming profile ids to be used in the query : (select profile_id from tname where profile_id in a_profile_id). --- For example : "select profile_id from dao.client where profile_id in (1234,2345) " Commented Sep 4, 2020 at 20:11

2 Answers 2

1

This solution is using the dynamic SQL, As per my knowledge we need to use the dynamic SQL if we have the table name in a variable.

DBFIDDLE working code

Query:

CREATE PROCEDURE dbo.de_dup (@a_profile_id NVARCHAR(MAX))
AS
BEGIN
    DECLARE @tname VARCHAR(max)
        ,@id INT
        ,@dynamicSQL NVARCHAR(MAX);
    DECLARE @matched_tables TABLE (Name NVARCHAR(255));
    DECLARE @matched_profileIds TABLE (profile_id INT);
    DECLARE @profile_ids NVARCHAR(MAX) = @a_profile_id

    INSERT INTO @matched_tables
    SELECT DISTINCT a.TABLE_SCHEMA + '.' + a.TABLE_NAME AS table_name
    FROM INFORMATION_SCHEMA.COLUMNS a
    WHERE a.COLUMN_NAME = 'profile_id'

    WHILE EXISTS (
            SELECT 1
            FROM @matched_tables
            )
    BEGIN
        SELECT TOP 1 @tname = [Name]
        FROM @matched_tables

        SET @dynamicSQL = CONCAT (
                'select profile_id from '
                ,@tname
                ,' WHERE '
                ,''','
                ,@profile_ids
                ,','''
                ,' LIKE '
                ,'''%,'
                ,''''
                ,' + CAST(profile_id AS NVARCHAR(MAX)) + '
                ,''',%'
                ,''''
                )

        PRINT @dynamicSQL;

        INSERT INTO @matched_profileIds
        EXEC (@dynamicSQL)

        DELETE
        FROM @matched_tables
        WHERE [Name] = @tname
    END

    SELECT *
    FROM @matched_profileIds
END

Dynamic SQL that gets formed is

SELECT profile_id FROM dbo.TestTable WHERE ',123,456,789,1011,1213,' LIKE '%,' + CAST(profile_id AS NVARCHAR(MAX)) + ',%'

Sign up to request clarification or add additional context in comments.

Comments

1

So I have solved a similar issue with a table-valued function called Split. It splits a delimited list into rows in a table, which you can then JOIN or use as a subquery in your code.

CREATE FUNCTION [dbo].[Split]
(
    @char_array varchar(500), @delimiter char(1)
)
RETURNS 
@parsed_array table
(
    Parsed varchar(50)
)
AS
BEGIN
    DECLARE @parsed varchar(50), @pos int

    SET @char_array = LTRIM(RTRIM(@char_array))+ @delimiter
    SET @pos = CHARINDEX(@delimiter, @char_array, 1)

    IF REPLACE(@char_array, @delimiter, '') <> ''
    BEGIN
        WHILE @pos > 0
        BEGIN
            SET @parsed = LTRIM(RTRIM(LEFT(@char_array, @pos - 1)))
            IF @parsed <> ''
            BEGIN
                INSERT INTO @parsed_array (Parsed) 
                VALUES (@parsed)
            END
            SET @char_array = RIGHT(@char_array, LEN(@char_array) - @pos)
            SET @pos = CHARINDEX(@delimiter, @char_array, 1)
        END
    END 
    RETURN
END
GO

You would use it like so

SELECT f.Parsed INTO #s FROM dbo.Split(@a_profile_id, ',') f;

Then in your query (only the relevant part for brevity)

select profile_id from @tname where profile_id in(select Parsed from #s);

I left out the set @id= because that will produce unpredictable results for the value of @id if the select statement returns multiple results. But you indicated this is not the actual code anyway so...

Disclaimer: I got the meat of the Split function from someone else online. If I could remember who I would attribute it properly.

2 Comments

You can use STRING_SPLIT if your sql-server version is 2016+
@SowmyadharGourishetty thanks, that built-in function is better than the ancient one I have been using!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.