【发布时间】:2021-10-28 05:23:17
【问题描述】:
检查在给定日期之前是否有任何订单(Date 列)。该过程有一个作为日期的传递参数“date”和另一个传递参数“count”。此参数返回此日期之前的订单数。
简单的做法是:
SELECT COUNT([Sales].[dbo].[Order].[Date])
FROM [Sales].[dbo].[Order]
WHERE [Sales].[dbo].[Order].[Date] >= '2019-03-11'
但不幸的是我必须使用程序和光标。我的尝试是这样的:
CREATE OR ALTER PROCEDURE OrderBeforeDate
(@date date,
@count int OUT)
AS
BEGIN
SET @count = 0;
DECLARE cursor1 SCROLL CURSOR FOR
SELECT [Sales].[dbo].[Order].[Date]
FROM [Sales].[dbo].[Order]
FOR READ ONLY
OPEN cursor1;
FETCH NEXT FROM cursor1 INTO @date
WHILE @@FETCH_STATUS = 0
BEGIN
IF @date <= '2019-03-11'
SET @count = @count + 1;
END
CLOSE cursor1;
DEALLOCATE cursor1;
END
DECLARE @count int
EXEC OrderBeforeDate @count OUT
PRINT 'Number of Orders after 2019-03-11'': ' + CAST(@count AS VARCHAR(10))
但我收到以下错误消息:
操作数类型冲突:int 与日期不兼容
我不知道该怎么办。请帮我一把。
【问题讨论】:
-
为什么要在这里使用光标? SQL 是一种基于集合的语言,在极少数情况下您应该使用它。
-
我完全同意你的看法,但这是该项目所需的默认设置。
-
听起来像一个非常有缺陷的项目,需要一个光标来完成这样的事情。
-
您的存储过程逻辑有缺陷。您有一个日期参数,但您没有正确使用它。您可以在游标定义中包含该参数,然后只计算它返回的行数。或者,您可以根据日期参数评估游标返回的每一行的日期,并根据需要递增。第二种方法 - 这是您实现的 - 需要另一个局部变量来接受来自光标的适当列。然后将您的参数与此局部变量进行比较。
-
还有一个坏习惯 - 使用 3 部分名称。过程通常存在于特定数据库中,并且将引用同一数据库中的对象(表)。使用三部分名称意味着更改数据库名称将需要更改代码。数据库名称更改很常见 - 不要在没有充分理由的情况下使用 3 部分名称。
标签: sql sql-server count cursor procedure