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

时间:2015-12-25 14:59:22

标签: c# sql sql-server

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

重要的是要注意我们无法修改我们正在配置的系统。

我相信系统是用C#构建的(.net肯定是C#是猜测)。

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

  1. 创建临时表
  2. 创建一个临时过程(插入到创建的表中)
  3. 拨打临时程序4次
  4. 读取临时表作为对系统呼叫的响应。
  5. 类似的东西:

    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中执行此脚本需要将GO放在上面示例的第7行中,否则系统报告的相同问题将在Management Studio中发生。

    我可以在此脚本中使用GO等效物来使其工作吗?

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

    我在Oracle中有一个背景,而且我仍然倾向于使用SQL服务器常用技巧......系统接受除了创建过程之外的多个命令,所以我倾向于相信有一个SQL Server技巧我可以在这里使用。

    提前谢谢!

4 个答案:

答案 0 :(得分:2)

问题在于语法上没有办法创建一个过程,然后在同一批次之后做一些事情。编译器不知道它的结束位置,而且分号之类的东西不能修复它(因为分号只会终止一个语句而不是一个批处理)。

使用动态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 :(得分:0)

1)如果您无法更改或向系统添加任何内容,请查看服务器上的权限。 即。创建程序陈述。

2)你可以做一个小练习

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

即。,a)创建你的#table      b)执行insert语句。      c)从你的#table中选择* 这应该让你回到你想从临时表中取回的数据注意我在这里跳过了整个过程。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

鉴于proc定义没有改变,对于在特定过程结束之后存在的过程中没有真正的伤害,它可以很容易地成为常规(即非临时的存储过程恰好存在于tempdb中。使用tempdb中创建的常规存储过程的好处是,在使用全局临时存储过程时,您无需担心潜在的名称冲突。该脚本只需要确保存储过程存在。但是无需手动删除存储过程或自动清除它。

以下代码改编自@ RBarryYoung' 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;

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