在系统中通过"ExecuteReader"执行多个 SQL 命令 我只能操作 SQL 语句



我必须配置一个系统,该系统为我提供了一个输入SQL语句的区域。

需要注意的是,我们不能修改正在配置的系统。

我相信这个系统是用C#构建的(当然是.net,但C#只是猜测)。

无论如何,我正在尝试创建一个脚本,该脚本将:

  1. 创建临时表
  2. 创建一个临时过程(插入到创建的表中)
  3. 调用临时过程4次
  4. 读取临时表作为对系统调用的响应

类似于:

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;

系统很可能通过C#SqlCommand.ExecuteReader()方法执行我的脚本。因为我可以在我创建的一个简单的C#应用程序中模拟这个问题。

问题是,在执行此脚本时,系统(或SQL Server)假定过程主体是整个脚本,并且似乎忽略了上例第6行中的;。我使用这个;的意图是标记过程创建的结束。

在Management studio中执行此脚本需要在上例的第7行中放置GO,否则Management studio中也会出现系统报告的相同问题。

我可以在这个脚本中使用等效的GO吗??

或者有更好的方法来编写这个脚本吗??

我有Oracle的背景,我仍然在学习SQL server的常用技巧。。。除了这里的创建过程之外,系统还接受多个命令,所以我倾向于相信我可以在这里使用SQL Server技巧。

提前谢谢!

问题在于,从语法上讲,没有办法创建一个过程,然后在同一批中执行它之后的操作。编译器不知道它在哪里结束,像分号这样的东西也无法修复它(因为分号只终止语句,而不是批处理)。

使用动态SQL,(并修复一个语法错误)这是可行的:

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)如果您不能更改或添加任何内容到系统中,请查看服务器上的权限。即,创建过程语句。

2) 你可以做一个小练习

使用SqlConnection()打开连接对象保持连接打开,直到您执行所有语句

即。,a) 创建#表b) 执行插入语句。c) 从#表中选择*这应该可以让您从临时表中返回想要返回的数据。注意,我在这里跳过了整个过程。

您可以执行由分号分隔的sql语句,而不是创建存储过程。您可以通过这种方式执行多个语句。此外,如果您想创建一个临时表并用数据加载它,您可以对多个sql命令使用相同的连接。

考虑到proc定义没有更改,在这个特定进程结束后,proc中没有真正的危害,它可以很容易地成为tempdb中恰好存在的常规(即非临时)存储过程。使用在tempdb中创建的常规存储过程的好处是,在使用全局临时存储过程时不必担心潜在的名称冲突。脚本只需要确保存储过程存在。但是,不需要手动删除存储过程或自动清理存储过程。

以下代码改编自@RBarryYoung的回答:

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;

这里唯一的区别是,非临时存储过程不在当前数据库的上下文中执行,而是像任何其他非临时存储程序一样,在其存在的数据库的上下文(在本例中为tempdb)中运行。因此,从中选择的表(即table2)需要完全合格。这意味着,如果proc需要在多个数据库中运行,并引用每个数据库的本地对象,那么这种方法可能不是一种选择。

最新更新