Sql server 2012 在填充日历的存储过程中,从字符串到日期的转换失败

Sql server 2012 在填充日历的存储过程中,从字符串到日期的转换失败,sql-server-2012,Sql Server 2012,这是我试图用来填充SQL Server中的表的存储过程: ALTER PROCEDURE [IMM1069].[uspVulKalender] @jaarVanaf varchar(10), @jaarTot varchar(10) AS declare @startdag varchar(20) declare @einddag varchar(20) declare @lopendeDag date = null declare @weekdag bit

这是我试图用来填充SQL Server中的表的存储过程:

ALTER PROCEDURE [IMM1069].[uspVulKalender]
   @jaarVanaf varchar(10),
   @jaarTot varchar(10)
AS
   declare @startdag varchar(20)
   declare @einddag varchar(20)
   declare @lopendeDag date = null
   declare @weekdag bit = 0

   set @startdag = '01/01/'+@jaarVanaf
   set @einddag = '31/12/'+@jaarTot

BEGIN

   set @lopendeDag = cast(@startdag as date)

   While @lopendeDag <= cast(@einddag as date)
     if datepart(dw,getdate()) = 6 or datepart(dw,getdate()) = 7
        set @weekdag = 0
     else
        set @weekdag = 1

     print(@lopendeDag)

     insert into [IMM1069].[tbl_kalender](tbl_kalender.datum, tbl_kalender.dag, tbl_kalender.dag_naam, tbl_kalender.isWeekdag, tbl_kalender.week, tbl_kalender.maand, tbl_kalender.maand_naam, tbl_kalender.jaar)
     values(
       @lopendeDag,               --datum
       datepart(dw,@lopendeDag),  -- weekdaynr
       datename(dw,@lopendeDag),  -- name day
       @weekdag,              -- isWeekday
       datepart(wk,@lopendeDag),  -- weeknr
       datepart(mm,@lopendeDag),  -- monthnr
       datename(mm,@lopendeDag),  -- monthname
       datepart(yyyy,@lopendeDag)
      )

     set @lopendeDag = dateadd(dd,1,@lopendeDag)
END
执行存储过程时出现以下错误:

Msg 241,16级,状态1,程序uspVulKalender,第21行 从字符串转换日期和/或时间时,转换失败

提前感谢您的帮助


Jannick

您已经将其标记为SQL Server 2012,因此您应该使用全新的FromParts方法。如果是类似日期或时间的项,则有相应的FromParts方法。在你的例子中,你看到的是来自零件的日期

我想Aaraon已经指出,不应该使用字符串来存储日期。考虑到你的非英语源代码,我认为国际化对于其他人来说并不是一个陌生的概念,现在我从我的肥皂盒中退出

你仍然有一个逻辑问题,但我要做的是

将@startdag和@einddag的数据类型更改为date。 不使用字符串连接,而是使用。
您的While循环比较简化为@lopendeDag,这是一种更有效的方法。每当你认为你将得到一堆行,然后一次循环一行,试着换一种方式思考。SQL Server经过优化,可以在集合中工作,而不是在循环中工作。以下是一个基于集合的备选方案:

ALTER PROCEDURE [IMM1069].[uspVulKalender]
  @jaarVanaf INT,
  @jaarTot   INT
AS
BEGIN
  SET NOCOUNT ON; 

  IF @jaarVanaf NOT BETWEEN 2010 AND 2030
    OR @jaarTot NOT BETWEEN 2010 AND 2030
  BEGIN
    RETURN;
  END

  ;WITH n(n) AS
  (
    SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_columns
  ), d(d) AS
  (
    SELECT DATEADD(DAY, n-1, DATEADD(YEAR, @jaarVanaf-1900, 0)) FROM n 
      WHERE n <= DATEDIFF(DAY, DATEADD(YEAR, @jaarVanaf-1900, 0), 
      DATEADD(YEAR, @jaarTot-1899, 0))
  )
  --insert into [IMM1069].[tbl_kalender]
  --(datum,dag,dag_naam,isWeekdag,week,maand,maand_naam,jaar)
  SELECT 
    d, 
    DATEPART(WEEKDAY, d),  -- datum
    DATENAME(WEEKDAY, d),  -- weekdaynr
    CASE WHEN DATEPART(WEEKDAY, d) IN (6,7) THEN 0 ELSE 1 END,  -- isWeekday
    DATEPART(WEEK, d),     -- weeknr
    DATEPART(MONTH, d),    -- monthnr
    DATENAME(MONTH, d),    -- monthname
    DATEPART(YEAR, d)      -- yearnr
  FROM d;
END
一些注意事项:

传递年份的整数。没有理由在这里传递字符串,然后使用连接来形成区域性的、不明确的日期字符串。 sys.all_columns查询应支持空数据库中约8400行,具体取决于SQL Server的版本。这将让你建立一个跨越23年的日期范围。如果需要更多,可以交叉连接到sys.objects,也可以创建自己的数字表。 insert不需要在每一列上都使用表前缀。我已经注释掉了上面的插入,因此您可以在尝试执行插入之前测试输出。 我已经详细说明了日期部分,而不是使用缩写,因为这些可能会引起混淆。例如,尝试选择DATEPARTY、GETDATE、DATEPARTW、GETDATE;-这会产生你期望的结果吗? 一些背景博文:


调用proc时,您提供了哪些值??为什么一年是一年?你知道有哪一年不是四个字符吗?另外,您的WHILE循环是无限的,我不认为您打算在每一行上插入星期四等-您的代码应该使用变量,而不是GETDATE…@jpw;我在执行存储过程时提供2年的时间,例如2014年为开始年,2015年为结束年。因此,该过程应该从2014年1月1日开始,直到2015年12月31日。嘿,Billinkc,我使用的是SQL Server 2012的快速版本。显然,DATEFROMPARTS函数在此版本中不是内置的,因为我在执行存储过程时遇到以下错误:DATEFROMPARTS不是可识别的函数名。但是Aaron已经解决了这个问题。谢谢你的努力!GrJannick@GrJannick您确定正在使用SQL Server 2012吗?选择什么@版本;说我打赌您使用的是2012 SSMS,但连接的是较旧的发动机。
ALTER PROCEDURE [IMM1069].[uspVulKalender]
  @jaarVanaf INT,
  @jaarTot   INT
AS
BEGIN
  SET NOCOUNT ON; 

  IF @jaarVanaf NOT BETWEEN 2010 AND 2030
    OR @jaarTot NOT BETWEEN 2010 AND 2030
  BEGIN
    RETURN;
  END

  ;WITH n(n) AS
  (
    SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_columns
  ), d(d) AS
  (
    SELECT DATEADD(DAY, n-1, DATEADD(YEAR, @jaarVanaf-1900, 0)) FROM n 
      WHERE n <= DATEDIFF(DAY, DATEADD(YEAR, @jaarVanaf-1900, 0), 
      DATEADD(YEAR, @jaarTot-1899, 0))
  )
  --insert into [IMM1069].[tbl_kalender]
  --(datum,dag,dag_naam,isWeekdag,week,maand,maand_naam,jaar)
  SELECT 
    d, 
    DATEPART(WEEKDAY, d),  -- datum
    DATENAME(WEEKDAY, d),  -- weekdaynr
    CASE WHEN DATEPART(WEEKDAY, d) IN (6,7) THEN 0 ELSE 1 END,  -- isWeekday
    DATEPART(WEEK, d),     -- weeknr
    DATEPART(MONTH, d),    -- monthnr
    DATENAME(MONTH, d),    -- monthname
    DATEPART(YEAR, d)      -- yearnr
  FROM d;
END