Sql server 使用游标计算所需表中的所有行
我的数据库中只有很少的表,我想根据AppointId计算所有这些表的总行数,我使用标量游标和表变量基于AppointId存储这些表的一些数据。在游标结束后,我对在游标中使用动态查询插入数据的表变量行进行计数 但它给了我以下的错误 必须声明表变量“@ProcCount” 是否有其他方法可以从必要的表中获取所有行的计数。 下面是我的代码:Sql server 使用游标计算所需表中的所有行,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我的数据库中只有很少的表,我想根据AppointId计算所有这些表的总行数,我使用标量游标和表变量基于AppointId存储这些表的一些数据。在游标结束后,我对在游标中使用动态查询插入数据的表变量行进行计数 但它给了我以下的错误 必须声明表变量“@ProcCount” 是否有其他方法可以从必要的表中获取所有行的计数。 下面是我的代码: Create FUNCTION [dbo].[ufn_GetProcedureCount] ( ) RETURNS INT AS BEGIN
Create FUNCTION [dbo].[ufn_GetProcedureCount]
(
)
RETURNS INT
AS
BEGIN
-- Declare the return variable here
DECLARE @MenuID bigINT, @TableName VARCHAR(150);
DECLARE @Result int
DECLARE @ProcCount TABLE (AppID INT, WoundId bigINT,TableName varchar(150));
DECLARE @sql nvarchar(2000)
DECLARE @Count int
DECLARE Cur_PendSign Cursor For
select Distinct MenuID,TableName from AppointmentTypeRequiredDocumnet A inner join Menu M on M.ID =A.MenuID where m.MenuGroupID = 8
OPEN Cur_PendSign
FETCH Cur_PendSign INTO @MenuID, @TableName
WHILE @@FETCH_STATUS=0
BEGIN
SET @sql='DECLARE @ProcCount TABLE (AppID INT, WoundId bigINT,TableName varchar(150))'
SET @sql=@sql+'INSERT INTO @ProcCount (AppID,WoundId)
SELECT TOP 1 V.AppointmentID, 1
FROM ['+@TableName+'] V WITH(NOLOCK)'
set @sql=@sql+ 'select count(*) from @ProcCount;'
--set @sql=@sql+ 'DECLARE @Count int'
EXECUTE sp_executesql @sql
FETCH Cur_PendSign INTO @MenuID, @TableName
END
CLOSE Cur_PendSign
DEALLOCATE Cur_PendSign
--set @Result = select count(*) from @ProcCount
RETURN @Result
END
脚本有两个问题 第一:缺少where子句 从约会A中选择Distinct MenuID、TableName。约会ID=8
第二:由于范围的限制,您需要创建持久表而不是变量表,因为您不能在EXEC之外声明变量表并使用它。此查询应该适合您。您需要使用
sp_executesql
执行动态查询
CREATE FUNCTION [dbo].[ufn_GetProcedureCount]
(
)
RETURNS INT
AS
BEGIN
-- Declare the return variable here
DECLARE @Result INT
DECLARE @ProcCount TABLE (
AppID INT,
WoundId BIGINT,
TableName VARCHAR(150)
)
DECLARE @MenuID BIGINT,
@TableName VARCHAR(150)
--Get all table which I need to count rows
DECLARE Cur_PendSign CURSOR FOR
SELECT DISTINCT MenuID, TableName FROM Appointment WHERE AppointmentID = 8
OPEN Cur_PendSign
FETCH Cur_PendSign INTO @MenuID, @TableName
WHILE @@fetch_status = 0
BEGIN
-- Insert require data into @ProcCount using dynamic query
DECLARE @query VARCHAR(255) = 'INSERT INTO @ProcCount (AppID,WoundId,TableName)
SELECT TOP 1 AppointmentID, WoundId, TableName
FROM [' + @TableName + '] WITH(NOLOCK) '
EXECUTE sys.sp_executesql @query
FETCH Cur_PendSign INTO @MenuID, @TableName
END
CLOSE Cur_PendSign
DEALLOCATE Cur_PendSign
--Get Count of all rows from tables
SELECT @Result = COUNT(*) FROM @ProcCount
RETURN @Result
END
如果没有
光标
,循环
,您可以通过动态编码来实现
模式:
(它可能与您的实际模式不同)
现在你喜欢下面的内容吗
DECLARE @QRY VARCHAR(MAX)='';
SELECT @QRY = @QRY+ 'SELECT COUNT(1) AS COUNT_TABLES FROM '+ TableName + ' (NOLOCK)
UNION ALL
' FROM (
SELECT DISTINCT TableName FROM #Appointment A WHERE A.AppointmentID = 8
)A
SELECT @QRY = SUBSTRING(@QRY,1,LEN(@QRY)-11)
SELECT @QRY = '
SELECT SUM(COUNT_TABLES) FROM (
' + @QRY+'
)A'
--PRINT @QRY
EXEC (@QRY)
如果您想检查@QRY包含的内容
/*
SELECT SUM(COUNT_TABLES) FROM (
SELECT COUNT(1) AS COUNT_TABLES FROM TABLE3 (NOLOCK)
UNION ALL
SELECT COUNT(1) AS COUNT_TABLES FROM TABLE4 (NOLOCK)
UNION ALL
SELECT COUNT(1) AS COUNT_TABLES FROM TABLE5 (NOLOCK)
)A
*/
您确定您需要游标,而仅仅使用联接无法实现所需的功能吗?导致光标减少performance@Pream,我需要一个光标,因为我在存储过程中使用它返回值。您仅从动态代码插入中选择
TOP 1
。然后,游标中只包含计数的表的数量。“不是吗?”沙克尔,游标里有15多张桌子。我用TOP1来检查它是否有效。看这个演示脚本,这是一个问题。如何创建持久表以及如何在此查询中使用它。使用临时表(##tablename)或普通表。游标中不允许使用临时表,因此我使用变量表游标中不允许使用临时表。对不起,我的错误,我们不能在用户定义的标量函数中使用临时表,我在函数中使用游标。@Hitesh,它在SQL Server 2008上对我有效。您是否可以添加表定义、插入脚本、测试数据以及从SQL Server收到的实际错误消息,以及严重性和状态,以便清楚地了解您的问题。@Vena,我刚刚更新了代码,但它创建的每个游标循环都有一个新的变量表,因此我无法获得计数cursor@Hitesh,您能否同时添加样本数据和预期输出?请参阅
/*
SELECT SUM(COUNT_TABLES) FROM (
SELECT COUNT(1) AS COUNT_TABLES FROM TABLE3 (NOLOCK)
UNION ALL
SELECT COUNT(1) AS COUNT_TABLES FROM TABLE4 (NOLOCK)
UNION ALL
SELECT COUNT(1) AS COUNT_TABLES FROM TABLE5 (NOLOCK)
)A
*/