对于培训课程,用户在主表startdt, enddt, time range, requester name
中插入cal_tr_requests
等信息。如果培训时间超过一天,enddt
将在startdt
之后。我创建了另一个表cal_tr_Multidate
以插入所有日期classId
和主表的时间范围。因此,如果cal_tr_requests
输入此内容:
ClassID -- req_start_Date---req_end_date ---req_time--requsetor_name
1234567 2016-08-30 2016-08-31 8:00-10:00 test
然后cal_tr_Multidates
表将输入:
ClassID --- ReserveDt ---- ReserveTm
1234567 2016-08-30 8:00-10:00
1234567 2016-08-31 8:00-10:00
我在使用循环创建存储过程时遇到问题。这就是我所拥有的:
Alter PROCEDURE [dbo].[AddTrainingRoomRq_test]
@req_start_date DateTime,
@req_end_date DateTime,
@req_times text,
@requestor_name text
AS
BEGIN
Declare
@ClassID int,
@Multidates int
--Create the ClassID as a random number
Set @ClassID = (SELECT CAST(RAND() * 1000000000 AS INT) AS [RandomNumber])
INSERT INTO cal_tr_requests
(ClassID, req_start_date, req_end_date, req_times, requestor_name, date_of_req)
VALUES (@ClassID,@req_start_date,@req_end_date,@req_times,@requestor_name,getdate())
set @Multidates = (select datediff(d, req_start_date, req_end_date)
from cal_tr_requests
where ClassID = @ClassID)
if @Multidates = 0
Insert into Cal_tr_Multidates (ClassID, ReserveDt,ReserveTm)
Values(@ClassID, @req_start_date, @req_times)
else if @Multidates > 0
While @Multidates = 0
begin
--do the insert for all dates with classid and reserveTm
End
END
有人可以指出我正确的方向吗? 提前谢谢。
答案 0 :(得分:1)
我的目的不是为您提供针对您的具体问题的完整解决方案,而是为了展示您应该能够实施以解决您的挑战的校长。
此站点上发布的许多t-sql解决方案确实有效,但它们通常无法扩展。我可以修复你的循环以使其工作,但用t-sql来解决这个问题并不是一个好方法。可扩展的t-sql是基于集合的,而不是程序性的。
这是一个基于集合的方法的示例,用于获取两个其他日期之间的所有日期:
DECLARE @dateBegin DATE = '20160830';
DECLARE @dateEnd DATE = '20160905';
WITH E1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS t(N))
,E2 AS (SELECT N = 1 FROM E1 AS a, E1 AS b)
,E4 AS (SELECT N = 1 FROM E2 AS a, E2 AS b)
,E8 AS (SELECT N = 1 FROM E4 AS a, E4 AS b)
,cteTally AS (SELECT N = 0 UNION ALL
SELECT N = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E8)
SELECT includedDates = DATEADD(DAY, cte.N, '20000101')
FROM cteTally AS cte
WHERE cte.N >= DATEDIFF(DAY, '20000101', @dateBegin)
AND cte.N <= DATEDIFF(DAY, '20000101', @dateEnd);
您在此处看到的大部分代码都是构建内联计数表。您可以使用数据库中的静态数字表执行相同的操作,这对于重用很有用,但在性能方面不会产生太大差异。
在任何情况下,我们在这里做的事情都会避免循环(对于SQL Server而言不合适),而是使用一组简单的数据来确定我们的日期。
祝你好运。答案 1 :(得分:0)
以下是处理日期的递归CTE示例:
DECLARE @req_start_date DateTime,
@req_end_date DateTime
SET @req_start_date = '2016-08-15'
SET @req_end_date = '2016-08-31'
;WITH X AS
(
SELECT @req_start_date AS VAL
UNION ALL
SELECT DATEADD(DD,1,VAL) FROM X
WHERE VAL < @req_end_date
)
SELECT *
FROM X
OPTION(MAXRECURSION 0)
这里是你的proc(摆脱了Sean上面所说的text
类型),并且不需要@multidates
if/else
块作为start=end
日期:
ALTER PROCEDURE [dbo].[AddTrainingRoomRq_test]
(
@req_start_date DateTime,
@req_end_date DateTime,
@req_times VARCHAR(100),
@requestor_name VARCHAR(100)
)
AS
BEGIN
DECLARE @ClassID INT
--Create the ClassID as a random number
Set @ClassID = (SELECT CAST(RAND() * 1000000000 AS INT) AS [RandomNumber])
INSERT INTO cal_tr_requests (ClassID, req_start_date, req_end_date, req_times, requestor_name, date_of_req)
VALUES (@ClassID,@req_start_date,@req_end_date,@req_times,@requestor_name,getdate())
;WITH X AS
(
SELECT @req_start_date AS VAL
UNION ALL
SELECT DATEADD(DD,1,VAL) FROM X
WHERE VAL < @req_end_date
)
INSERT INTO Cal_tr_Multidates (ClassID, ReserveDt,ReserveTm)
SELECT @ClassID, VAL, @req_times
FROM X
OPTION(MAXRECURSION 0)
END