Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 根据条件将数据从表1归档到表2 | Sql Server 2017 Express_Sql Server_Archive_Auto Update - Fatal编程技术网

Sql server 根据条件将数据从表1归档到表2 | Sql Server 2017 Express

Sql server 根据条件将数据从表1归档到表2 | Sql Server 2017 Express,sql-server,archive,auto-update,Sql Server,Archive,Auto Update,我有一个包含两个表的数据库: 表Student,包括以下内容 栏目: 表ArchivedStudent包含以下列: ArvchivedStudentID int identity, StudentID int, StudentFN, StudentLN, WithdrawalDate getdate(), ReasonDropped 从长远来看,我希望为表acrchivedstudio安排自动更新,并将数据从列StudentID、StudentFN和StudentLN从表Studen

我有一个包含两个表的数据库:

Student
,包括以下内容 栏目:

ArchivedStudent
包含以下列:

ArvchivedStudentID int identity, 
StudentID int, 
StudentFN, 
StudentLN, 
WithdrawalDate getdate(), 
ReasonDropped
从长远来看,我希望为表
acrchivedstudio
安排自动更新,并将数据从列
StudentID、StudentFN
StudentLN
从表Student移动到表
archnivedstudion
,当列活动从1(true)变为0(false)

以下是我的启动脚本,它不起作用:

update [as]
set [as].StudentID = s.StudentID,
 [as].StudentFN = s.StudentFN,
 [as].StudentLN = s.StudentLN
from ArchivedStudent [as]

 inner join Student s
on [as].StudentID = s.StudentID
where s.Active = 0

go
问题是它不会返回任何结果

一旦我能够更新表
ArchivedStudent
,我想删除学生表中活动状态更改为0的学生的数据

您需要两个查询:

插入

Insert into archivedstudent (studentid, student, studentln) select studentid, studentfn, studentln from student where active=0 and studentid not in (select studentid from archivedstudent);
删除

Delete from student  where studentid in (select studentid from archivedstudent);

你的问题在过程中还不是很清楚。例如,您是希望在将学生移动到存档表之前让学生停用一段时间,还是希望学生在停用后立即移动到存档表

如果是后者,这要容易得多:

INSERT INTO ArchivedStudent (StudentId, StudentFn, StudentLn, WithdrawalDate)
SELECT S.StudentId, S.StudentFn, S.StudentLn, GETDATE()
FROM Student S
WHERE StudentId = ?

DELETE FROM Student WHERE StudentId = ?
如果是前者,则更具挑战性,我们需要更多细节

更新1:

要根据计算值设置取款日期,请使用以下命令:

INSERT INTO ArchivedStudent (StudentId, StudentFn, StudentLn, WithdrawalDate)
SELECT S.StudentId, S.StudentFn, S.StudentLn, CAST(DATEADD(D,14,GETDATE()) AS DATE)
FROM Student S
WHERE StudentId = ?
注1:在DATEADD()中,未来日期使用正值,过去日期使用负值。如果需要日期之外的实际时间,可以删除日期强制转换


注2:原始答案中的删除脚本仍然有效。

您需要的是触发器。但是,您应该小心处理大量数据上的触发器,它们可能会影响性能

您需要一个触发器来执行此操作:

CREATE TRIGGER ArchiveStudent ON Student 
   FOR UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    INSERT INTO ArchivedStudent (StudentID, StudentFN, StudentLN)
    SELECT 
        StudentID
    ,   StudentFN
    ,   StudentLN
    FROM 
        Student 
    WHERE 
        Active = 0


    DELETE FROM Student
    WHERE 
        Active = 0  
END
然而,你的方法很简单,同时也有风险。例如,如果有人错误地使某个学生处于非活动状态,则触发器将立即将该学生插入存档表,然后将其删除。当然,您可以通过多种方式检索它,例如删除、插入表,甚至获取归档表的最大id,但为什么您首先要将自己置于这种情况下呢?。这是当前方法可能遇到的许多一般性问题之一。更好的方法是为表添加更多的版本控制或历史记录方法,并使归档文件在固定日期而不是触发器上从SQL作业或存储过程运行。这将为您提供一个计划的、受控的数据归档


您甚至可以添加一个historian列,它将存储活动列的值和更改日期。然后,使用trigger或store过程为您执行此操作(甚至是一个带有通用标量函数的计算列,它将在多个表上重用)。例如,如果学生在5个工作日内处于非活动状态,则将其存档并从表中删除。

您可以在更新学生表后使用触发器

此触发器将:
-仅在更新时作出反应,
-当Active设置为0时,将学生转移到ArchiveStudent -并将提款日期设置为从今天起2周

触发:

演示:


您可以看看SQLFiddle解决方案

这里有许多解决方案似乎都部分正确,但存在一些问题。存档表的初始更新不会插入到存档表中,只会更新现有行。而且,由于您试图在live表和archive表之间联接,因此不会得到任何结果,因为update语句无论如何都不会产生“结果”,所以也不会得到任何更新

正如其他人所说,您将使用两条语句——一条是insert语句,另一条是delete语句。我倾向于谨慎行事,确保a)我的存档表中没有重复项,b)在我确定它进入存档之前,不要从live中删除。因此,这两种说法是:

insert archivestudent(...fieldlist...)
select * from student 
where active=0
and not exists(select * from archivestudent where archivestudent.studentid=student.studentid)

delete student 
where active=0 
and exists(select * from archivestudent where archivedstudent.studentid=student.studentid)
然后,您可以随时运行此代码,将其安排为每晚运行的作业,无论在应用程序中有何意义


另一方面,如果您想立即运行,那么触发器就是一种方法。请注意,触发器是基于集合的操作,这意味着触发器对受更新影响的所有行运行一次。这意味着如果触发更新影响多行,@millan提出的解决方案将失败,因为子句
WHERE StudentID=(选择DELETED.[StudentID]FROM DELETED)
将返回多个值。例如,
updatestudent set active=0,其中enrolmentdateWelcome to StackOverflow!目前还不清楚您使用的是什么技术,您需要什么帮助。请澄清使用标签部分,我们将很乐意为您提供帮助。还有,看一看。干杯:)有什么帮助吗?嘿,不幸的是,现在还不清楚你到底在问什么。如果你想让我们为你写代码,你很可能得不到答案。如果情况并非如此,请描述您迄今为止所做的努力以及面临的问题。干杯:-)哦,对不起。启动代码不起作用(未返回任何结果):更新[as]集[as]。StudentID=s.StudentID[as]。StudentFN=s.StudentFN[as]。StudentLN=s.StudentLN从ArchivedStudent[as]内部加入[as]上的学生s。StudentID=s.StudentID其中s.Active=0 goI刚刚编辑了您的问题,以便大家都清楚(我的编辑仍在审阅队列中,所以请给它一点时间显示出来)。不幸的是,我也在审阅队列中看到了您的问题,个人对sql server一无所知。因此,我对该问题给予了一些奖励,以便它能出现在头版,并希望得到更多关注。快乐编码:)如果这是答案,请你把它标为已回答好吗?是的!一旦学生的状态更改为非活动状态,我想立即将其移动到存档表。Do
CREATE TRIGGER [Student_Changed] 
   ON  Student
   AFTER UPDATE
AS 
BEGIN
    -- Archive
    INSERT INTO ArchiveStudent
        (StudentID, StudentFN, StudentLN, WithdrawalDate)
    SELECT
        DELETED.StudentID
        ,DELETED.[StudentFN]
        ,DELETED.[StudentLN]
        ,DATEADD(day, 14, GETDATE()) -- 2 Weeks from today
    FROM DELETED
    WHERE DELETED.Active = 1

    -- Delete archived
    DELETE FROM Student
    WHERE StudentID = (SELECT DELETED.[StudentID] FROM DELETED)
        AND Active = 0
END;
insert archivestudent(...fieldlist...)
select * from student 
where active=0
and not exists(select * from archivestudent where archivestudent.studentid=student.studentid)

delete student 
where active=0 
and exists(select * from archivestudent where archivedstudent.studentid=student.studentid)
delete student
from deleted
join student on student.studentid=deleted.studentid
where active=0