【问题标题】:Create a function for counting rows from any table创建一个函数来计算任何表中的行数
【发布时间】:2014-11-05 17:33:30
【问题描述】:

我有这个用户定义的函数:

 CREATE FUNCTION [dbo].[COUNT_ROWS_TABLE]()
 RETURNS TINYINT
 AS
 BEGIN
      DECLARE @ROW_COUNT TINYINT
      SELECT @ROW_COUNT = COUNT(*) FROM EMPLOYEE
      RETURN @ROW_COUNT
 END
 GO

问题是它只适用于表[dbo].[EMPLOYEE],我不想为我数据库上的每个表复制粘贴这个函数。

到目前为止我的尝试:

 CREATE FUNCTION [dbo].[COUNT_ROWS_TABLE](@TABLE_NAME VARCHAR(50))
 RETURNS TINYINT
 AS
 BEGIN
      DECLARE @SQL_COMMAND NVARCHAR(100)
      DECLARE @PARAM NVARCHAR(50)
      DECLARE @ROW_COUNT TINYINT
      SET @SQL_COMMAND = N'SELECT @RESULT = COUNT(*) FROM ' + @TABLE_NAME
      SET @PARAM = N'@RESULT TINYINT OUTPUT'
      EXEC SP_EXECUTESQL @SQL_COMMAND, @PARAM, @RESULT = @ROW_COUNT OUTPUT
      RETURN @ROW_COUNT
 END
 GO

该代码不起作用,因为它不允许在函数中使用这些语句。 不过,它在存储过程中工作,但前提是我 PRINT 变量而不是 RETURN 它。

我需要它是一个函数,因为我需要在 IF 语句上调用它。

关于如何实现这一目标的任何想法?谢谢。

【问题讨论】:

  • 小音?所以你的表都不会包含超过 255 行?!?
  • @Philip Kelley 是的,因为它仅供个人使用(无论如何它是一个小型数据库)。我所有的桌子大约有 100-200 行...... 230 行顶部。所以,我不想在这种情况下使用不必要的(和更大的)类型。谢谢你的建议。

标签: sql sql-server function dynamic


【解决方案1】:

你可以像下面这样使用

ALTER FUNCTION [dbo].[COUNT_ROWS_TABLE](@TABLE_NAME VARCHAR(50))
 RETURNS TINYINT
AS
BEGIN
DECLARE @ROW_COUNT TINYINT
SELECT @ROW_COUNT = SUM(b.rows) 
FROM SYS.TABLES a INNER JOIN sys.partitions b ON b.OBJECT_ID = a.OBJECT_ID
WHERE a.is_ms_shipped = 0 AND b.index_id IN (1,0)
        and a.name=@TABLE_NAME
GROUP BY a.name

RETURN @ROW_COUNT
END
GO

【讨论】:

  • +1 但为什么用 a 和 b 代替别名,我不知道,t 和 p?您也可以只使用RETURN (SELECT SUM(b.rows...) FROM ...); 进行简化,而不必使用局部变量。
【解决方案2】:

对于这种将对象名称作为参数传递的查询,您将需要使用 Dynamic Sql,但由于您只返回总行数,因此可以使用 sys 模式目录视图和 Dynamic sql 来实现,您不能在 UDF 定义中使用动态 Sql。

带有 OUTPUT 参数的存储过程

这是你需要做的.....

 CREATE PROCEDURE [dbo].[COUNT_ROWS_TABLE]
  @TABLE_NAME SYSNAME,
  @Count      INT      OUTPUT
 AS
 BEGIN
   SET NOCOUNT ON;

      DECLARE @Sql NVARCHAR(MAX);

      SET @Sql  = N'SELECT @Count = COUNT(*) FROM ' + QUOTENAME(@TABLE_NAME)

  EXECUTE sp_executesql @Sql
                     , N'@Count INT OUTPUT'
                     , @Count OUTPUT

 END
 GO

使用 sys 架构的函数

 CREATE FUNCTION [dbo].[COUNT_ROWS_TABLE]
  (
    @TableName SYSNAME
   )
 RETURNS INT
 AS
 BEGIN
   DECLARE @Row_Count INT;

    SELECT @Row_Count = i.rowcnt 
    FROM sysindexes AS i
    INNER JOIN sysobjects AS o  ON i.id = o.id 
    WHERE i.indid < 2  AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0
     AND o.NAME = @TableName

  RETURN @Row_Count;

END

【讨论】:

  • (1) 我永远不会直接对表格进行计数。为什么?所有这一切都会阻止,对查询 DMV/目录视图的影响要小得多。 (2) 我更喜欢您的第二个查询,但请,请,请停止使用 sysindexes/sysobjects。这些是已弃用的向后兼容性视图。 (它也不处理分区表。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 2013-01-18
  • 2014-11-12
  • 2020-03-30
  • 2019-03-11
  • 2018-10-16
  • 2018-04-15
相关资源
最近更新 更多