简体   繁体   中英

Multiple SQL commands executed via “ExecuteReader” in a system I can only manipulate SQL statements

I have to configure a system which provides me with an area to input SQL statements.

It is important to notice that we cannot modify the system we are configuring.

I believe the system was built in C# (.net for sure but C# is a guess).

Any way, I'm trying to create a script that would:

  1. create a temporary table
  2. create a temporary procedure (which inserts into the table created)
  3. call the temporary procedure 4 times
  4. Read the temp table as a response to the system's call.

Something like:

CREATE Procedure #myTempProcedure(
  @param1 nvarchar(max)
) as 
begin
  insert #tempTable (col1, col2) select aCol, bCol from table2 where col2 = @param1;
end;


CREATE TABLE #tempTable
(col1 nvarchar(512),
(col2 nvarchar(512));

EXEC #myTempProcedure N'val1';
EXEC #myTempProcedure N'val2';
EXEC #myTempProcedure N'val3';
EXEC #myTempProcedure N'val4';

select col1, col2 from #tempTable;

The system is very likely executing my script via C# SqlCommand.ExecuteReader() method. As I can simulate the problem in a simple C# application I created.

The problem is that when executing this script, the system (or SQL Server) assumes the procedure body to be the entire script and seems to disregard my ; in line 6 of the example above. My intention with this ; was to flag the end of the procedure creation.

Executing this script in Management studio requires a GO to be placed in line 7 of the example above, otherwise the same problem reported by the system would happen in Management Studio.

Is there a GO equivalent I could use in this script to get it to work??

Or is there a better way to script this??

I have a background in Oracle, and I'm still leaning SQL server usual tricks... The System accepts multiple commands apart from the create procedure here, So I'm inclined to believe there is a SQL Server trick I could use here.

Thank you in advance!

The problem is that syntactically there is no way to create a procedure and then do something after it in the same batch. The compiler doesn't know where it ends, and things like semi-colon don't fix it (because semi-colon only terminates a statement, not a batch).

Using dynamic SQL, (and fixing one syntax error) this works:

EXEC('
    CREATE Procedure ##myTempProcedure(
        @param1 nvarchar(max)
    ) as 
    begin
      insert #tempTable (col1, col2) select aCol, bCol from table2 where col2 = @param1;
    end;
');


CREATE TABLE #tempTable
(
    col1 nvarchar(512),
    col2 nvarchar(512)
);

EXEC ##myTempProcedure N'val1';
EXEC ##myTempProcedure N'val2';
EXEC ##myTempProcedure N'val3';
EXEC ##myTempProcedure N'val4';

select col1, col2 from #tempTable;

EXEC('DROP PROC ##myTempProcedure;');

1) please look at the rights on the server you many have some issues with if you cannot change or add anything to the system. ie., Create procedure statements.

2) you could do a small exercise

open a connection object using the SqlConnection() keep the connection open till you execute all you statements

ie., a) create your #table b) execute your insert statement. c) select * from your #table this should get you back the data you are intending to get back from your temp table note i skipped the entire proc here.

Instead of creating stored procedure, you can execute sql statements delimited by semi colon. You can execute multiple statements this way. Also if you want to create a temp table and load it with data, you can use the same connection with multiple sql commands.

Given that the proc definition doesn't change, and that there is no real harm in the proc existing beyond the end of this particular process, it could just as easily be a regular (ie non-temporary) Stored Procedure that just happens to exist in tempdb . The benefit of using a regular Stored Procedure created in tempdb is that you do not need to worry about potential name collisions when using global temporary stored procedures. The script simply needs to ensure that the stored procedure exists. But there is no need to remove the Stored Procedure manually or have it automatically cleaned up.

The following code is adapted from @RBarryYoung's answer :

IF (OBJECT_ID(N'tempdb.dbo.myTempProcedure') IS NULL)
BEGIN
  USE [tempdb];

  EXEC('
      CREATE PROCEDURE dbo.myTempProcedure(
          @param1 NVARCHAR(MAX)
      ) AS 
      BEGIN
        INSERT INTO #tempTable (col1, col2)
          SELECT aCol, bCol
          FROM table2
          WHERE col2 = @param1;
      END;
');
END;

CREATE TABLE #tempTable
(
    col1 NVARCHAR(512),
    col2 NVARCHAR(512)
);

EXEC tempdb.dbo.myTempProcedure N'val1';
EXEC tempdb.dbo.myTempProcedure N'val2';
EXEC tempdb.dbo.myTempProcedure N'val3';
EXEC tempdb.dbo.myTempProcedure N'val4';

SELECT col1, col2 FROM #tempTable;

The only difference here is that a non-temporary Stored Procedure does not execute in the context of the current database, but instead, like any other non-temporary Stored Procedure, runs within the context of the database where it exists, which in this case is tempdb . So the table that is being selected from (ie table2 ) needs to be fully-qualified. This means that if the proc needs to run in multiple databases and reference objects local to each of them, then this approach is probably not an option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM