如何解决SQL Server 2008:复杂插入
| 我有一张叫ѭ0的表:BeginYear | EndYear | Name
1974 1983 Robert
对于Employees
中的每条记录,我需要将每年插入到名为EmployeeYears
的新表中
所以:
For Each Record in Employees
For i as int = Begin Year to End year
INSERT i,Name into EmployeeYears
在SQL中执行此操作的任何方法...可能使用游标吗?
解决方法
其要旨是使用WITH语句创建所有记录并将其插入到最终表中。
;WITH q AS (
SELECT Year = BeginYear,Name
FROM Employees
UNION ALL
SELECT q.Year + 1,q.Name
FROM q
INNER JOIN Employees e ON e.Name = q.Name
AND e.EndYear > q.Year
)
INSERT INTO EmployeeYears
SELECT * FROM q
OPTION(MAXRECURSION 0)
测试数据
CREATE TABLE Employees (BeginYear INTEGER,EndYear INTEGER,Name VARCHAR(32))
CREATE TABLE EmployeeYears (Year INTEGER,Name VARCHAR(32))
INSERT INTO Employees
SELECT 1974,1976,\'Robert\'
UNION ALL SELECT 1972,1975,\'Lieven\'
结果
SELECT *
FROM EmployeeYears
ORDER BY Name,Year
1972 Lieven
1973 Lieven
1974 Lieven
1975 Lieven
1974 Robert
1975 Robert
1976 Robert
,如果您有数字表,则可以加入该表以获取各个年份的记录,并避免使用光标。我只是用从1965年到968年的数字填充了数字表,但是一个realife数字表(出于示例目的,它也不会是一个临时表,如下所示,但它存在于您的模式中)可能会有几百万条记录对于很多比较有用。
create table #Numbers (Number int)
insert into #Numbers
select 1965
union
select 1966
union
select 1967
union
select 1968
create table #employees (name varchar (50),beginyear int,endyear int)
insert into #employees
select \'Dick\',1966,1968
union all
select \'harry\',1965,1967
union all
select \'tom\',1955,1966
insert into EmployeeYears (Name,[Year])
select Name,n.number
from #Employees e
join #Numbers n on n.number between e.beginyear and e.endyear
order by name
,是的,您实际上必须做一个循环...我宁愿不使用CURSORS,但这种情况sorta还是有道理的...无论如何,这里的代码只是一个直接循环,向您展示了您可以做的事情SQL中的这种代码:
DECLARE @Employee VARCHAR(100)
DECLARE @BeginYear INT,@EndYear INT,@i INT
SET @Employee = \'\'
WHILE (1=1)
BEGIN
SET @Employee = (SELECT TOP 1 Name FROM Employees ORDER BY Name WHERE Name > @Employee)
IF @Employee IS NULL BREAK
SELECT @BeginYear = BeginYear,@EndYear = EndYear FROM Employees WHERE Name = @Employee
SET @i = @BeginYear
WHILE (@i <= @EndYear)
BEGIN
INSERT INTO EmployeeYears (Year,Name) VALUES (@i,@Employee)
SET @i = @i + 1
END
END
,您可以使用递归CTE:
;WITH CTE AS
(
SELECT BeginYear,EndYear,Name
FROM Employees
UNION ALL
SELECT BeginYear+1,Name
FROM CTE
WHERE BeginYear < EndYear
)
INSERT INTO EmployeeYears (Year,Name)
SELECT BeginYear,Name
FROM CTE
ORDER BY Name,BeginYear
OPTION(MAXRECURSION 0)
,您可以使用递归过程。就像一个波纹管:
CREATE Procedure InsertYear
@Name ....
@BeginYear ...
@EndYear ...
AS
{
INSERT INTO EmployeeYears VALUES(@BeginYear,@Name);
SET @BeginYear = @BeginYear + 1
IF @BeginYear < @EndYear
BEGIN
InsertYear(@Name,@BeginYear,@EndYear)
END
RETURN
}
,您可以这样做,但是如果Begin或end超过2047,它将失败
INSERT INTO EmployeeYears (number,name)
SELECT v.number,e.name
FROM
Employees e
INNER JOIN master..spt_values v on
v.number between beginYear and endYear
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。