SQL消息8114,级别16,状态5,过程sp_product_listing,行0错误将数据类型varchar转换为datetime

时间:2012-03-19 21:40:03

标签: sql-server

/ 我是SQL的新手,我被要求创建一个程序以某种方式成功创建过程但是当我尝试运行执行时它不起作用。     有人可以帮我一把吗? /

CREATE PROCEDURE sp_product_listing
(
@product varchar(40) ='%',
@month datetime,
@year datetime 
)
AS
SELECT
products.name AS product_name,
products.unit_price,
products.quantity_per_unit,
suppliers.name AS supplier_name
FROM products
INNER JOIN suppliers ON products.supplier_id=suppliers.supplier_id
INNER JOIN order_details ON products.product_id=order_details.product_id
INNER JOIN orders ON order_details.order_id=orders.order_id
WHERE products.name LIKE @product 
AND
@month=CONVERT(char(10),MONTH(orders.order_date))
AND
@year=CONVERT(char(10),YEAR(orders.order_date))

运行错误     当我运行执行     执行sp_product_listing     '插口',     '六月',     '2001'

这是我收到的错误消息

  

Msg 8114,Level 16,State 5,Procedure sp_product_listing,Line 0       将数据类型varchar转换为datetime时出错。

是我坚持的月份和年份。

3 个答案:

答案 0 :(得分:2)

如果您的order_date列包含索引,则最好使用MONTH()DATEPART()等范围查询。您可以将月/年组合作为单个日期时间,或者您可以简单地将参数更改为整数,如下所示。

CREATE PROCEDURE dbo.sp_product_listing
  @product VARCHAR(40) = '%',
  @year SMALLINT,
  @month TINYINT
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @d SMALLDATETIME;

  SET @d = DATEADD(MONTH, @month - 1, 
    DATEADD(YEAR, @year-1900, '19000101'));

  SELECT ...
  WHERE Orders.order_date >= @d
    AND Orders.order_date < DATEADD(MONTH, 1, @d);
END
GO

答案 1 :(得分:1)

问题在于:

@month datetime,
@year datetime 

这两个参数都声明为datetime,但datetime变量包含完整的日期和时间信息(年,月,日,小时,分钟,秒......)。

您正在为@month参数传递'June',这不起作用,因为'June'是string@monthdatetime。这就是错误信息所说的内容。

答案 2 :(得分:0)

避免按部分过滤日期,因为这会使日期列上的索引无法使用。如果将@month和@year定义为varchars或ints,则可以构建整月的日期时间范围,并使用此范围过滤orders.order_date。

CREATE PROCEDURE sp_product_listing
(
    @product varchar(40) ='%',
    @month varchar(10),
    @year varchar(4) 
)
AS
    declare @firstOfMonth datetime
    set @firstOfMonth = convert(datetime, @month + ' 1, ' + @year, 100)

    SELECT
    products.name AS product_name,
    products.unit_price,
    products.quantity_per_unit,
    suppliers.name AS supplier_name
    FROM products
    INNER JOIN suppliers ON products.supplier_id=suppliers.supplier_id
    INNER JOIN order_details ON products.product_id=order_details.product_id
    INNER JOIN orders ON order_details.order_id=orders.order_id
    WHERE products.name LIKE @product 
    AND
         orders.order_date >= @firstOfMonth
    AND  -- before first of next month
         orders.order_date < dateadd(m, 1, @firstOfMonth)