【问题标题】:MS SQL Stored Procedure for counting Dynamic table items用于计数动态表项的 MS SQL 存储过程
【发布时间】:2012-07-21 12:49:46
【问题描述】:

我在下面的存储过程中写了这个并且得到了不正确的语句。

ALTER PROCEDURE dbo.[Counter]
        @TableName VARCHAR(100)
    AS 
        BEGIN
            DECLARE @Counter INT
            DECLARE @SQLQ VARCHAR(200)
            SET NOCOUNT ON;

        --SET @TableName = 'Member';
        SET @SQLQ = 'SELECT COUNT(*) FROM dbo.[' + @TableName + ']';
        --Preparing the above sql syntax into a new statement(get_counter).

            --Getting an error here I had googled the prepare statement but don't know why facing this error.
        PREPARE get_counter FROM @SQLQ;
    @Counter = EXEC get_counter; -- here @resutl gets the value of the count.@TableName
        DEALLOCATE PREPARE get_counter; -- removing the statement from the memory.


    END

然后我又写了一篇:

ALTER PROCEDURE dbo.[Counter]
    @TableName VARCHAR(100)
AS 
    BEGIN
        DECLARE @Counter INT
        DECLARE @SQLQ VARCHAR(200)
        SET NOCOUNT ON;

        --SET @TableName = 'Member';
        SET @SQLQ = 'SELECT COUNT(*) FROM dbo.[' + @TableName + ']';
        --Preparing the above sql syntax into a new statement(get_counter).


    Execute @SQLQ; -- here @resutl gets the value of the count.@TableName

        --DEALLOCATE PREPARE get_counter; -- removing the statement from the memory.
        Return @Counter;

    END

它运行正常,但我无法在 Counter 中得到结果,请任何人帮助我(我知道我没有为计数器分配任何值,但如果我这样做了,我会出错)。

在你回答马丁之后,我已经用你的代码替换了我的代码:

ALTER PROCEDURE dbo.[Counter] @SchemaName SYSNAME = 'dbo' , @TableName  SYSNAME

AS
  BEGIN
      SET NOCOUNT ON;

      DECLARE @SQLQ NVARCHAR(1000)
      DECLARE @Counter INT;

      SET @SQLQ = 'SELECT @Counter = COUNT(*) FROM ' + 
       Quotename(@SchemaName) + '.' + Quotename(@TableName);

      EXEC sp_executesql
        @SQLQ ,
        N'@Counter INT OUTPUT',
        @Counter = @Counter OUTPUT

      Return   SELECT @Counter
  END 

现在我已经找回了它。

  ALTER PROCEDURE dbo.[CreateBusinessCode]
    @MemberID                               bigint,
    @len                                        int,
    @RewardAccountID                bigint,
    @ConnectionStatusID         tinyint,
    @Assign                                 smalldatetime

AS
    BEGIN
    SET NOCOUNT ON;
    DECLARE @counter INT

    EXEC @counter = dbo.Counter 'dbo','member';

    Select @counter;


    END

【问题讨论】:

    标签: sql sql-server sql-server-2008 stored-procedures stored-functions


    【解决方案1】:

    您应该使用SYSNAME 作为对象标识符,使用Quotename 而不是自己连接方括号。

    ALTER PROCEDURE dbo.[Counter] @TableName  SYSNAME,
                                  @SchemaName SYSNAME = 'dbo'
    AS
      BEGIN
          SET NOCOUNT ON;
    
          DECLARE @SQLQ NVARCHAR(1000)
          DECLARE @Counter INT;
    
          SET @SQLQ = 'SELECT @Counter = COUNT(*) FROM ' + 
           Quotename(@SchemaName) + '.' + Quotename(@TableName);
    
          EXEC sp_executesql
            @SQLQ ,
            N'@Counter INT OUTPUT',
            @Counter = @Counter OUTPUT
    
             SELECT @Counter
      END 
    

    【讨论】:

    【解决方案2】:

    在 SQL Server 中,如果要将结果放入变量中,有两种选择。

    首先是使用游标。

    二是做动态SQL:

    declare @sql varchar(max) = whatever;
    declare @cnt int;
    
    declare @cntTable table as (cnt int);
    
    insert into @cntTable
        exec(@sql);
    
    select @cnt = t.cnt
    from @cntTable
    

    这很麻烦,但其中一个确实有效。

    【讨论】:

    • 如果尝试 Select 语句而不是 insert into 语句会发生什么?你能解释一下吗?
    • 这行不通。您可以将 exec 语句的输出插入到表中。您无法从中进行选择。 (对于 select,SQL Server 需要在编译查询时知道表的结构。它没有 exec 语句的信息。)
    【解决方案3】:

    试试这个。它不会查询实际表,但会为您提供行数。如果您有大表并且需要近似计数,这是更好的方法。

    ALTER PROCEDURE dbo.[Counter] 
        @TableName VARCHAR(100) 
    AS  
    begin
    
    declare @objectid int,@counter int
    select @objectid = object_id from sys.all_objects where name = @tablename and schema_id=SCHEMA_ID('dbo')
    select @counter = sum(rows) from sys.partitions where object_id= @objectid
    and index_id in (0,1)
    select @counter
    end
    go
    

    【讨论】:

    • 谢谢。这也很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-20
    相关资源
    最近更新 更多