【问题标题】:SQL Msg 8114, Level 16, State 5, Procedure sp_product_listing, Line 0 Error converting data type varchar to datetimeSQL 消息 8114,级别 16,状态 5,过程 sp_product_listing,第 0 行错误将数据类型 varchar 转换为 datetime
【发布时间】:2012-03-19 21:40:03
【问题描述】:

/我是 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'

这是我收到的错误消息

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

月份和年份是我被困在的那个。

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    如果您的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
    

    【讨论】:

      【解决方案2】:

      问题是这样的:

      @month datetime,
      @year datetime 
      

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

      您为@month 参数传递了“June”,这不起作用,因为“June”是string@monthdatetime。这就是错误消息的内容。

      【讨论】:

      • @Elgin 传入一个日期时间参数或两个数字(请参阅我的回答 - 再次抱歉格式化)。
      • 谢谢@Christian。转到 meta 看看是否有任何主题抱怨移动设备上的格式化。不好玩。
      【解决方案3】:

      避免按部分过滤日期,因为这会使日期列上的索引不可用。如果您将 @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)
      

      【讨论】:

      • 我仍然不喜欢传入字符串 'June' 和所有暗示的承诺(这取决于区域和语言设置是否已修复)。
      • 啊...我需要一些时间来消化它哈哈....我在这方面还是很陌生。老师要求我们用'June'而不是数字来运行和测试.....:(
      • 哈哈,这也是我的项目 arg 我认为使用 datename 也可以,但老师根本没有教任何关于 datename 的内容,只告诉了我们关于 datepart、diff 和添加
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 2017-06-01
      相关资源
      最近更新 更多