我有两个桌子。设备表和位置表。设备表中只能有一个设备,但是位置表中可以有多个具有多个位置的设备。
如果用户删除设备,我还需要从位置表中删除具有相同ID的位置。
是否可以从cfc页内从Delete语句(使用sql server)的多个表中删除?
当我进行初始删除时,我试图写一个<cfif>
,以检查是否有记录被删除,如果是,请运行下一个delete语句,该语句从表中删除设备。
我也尝试过使用这种格式。
delete T1, T2
from T1
inner join T2 on T1.device_id = T2.device_id
where T2.device_id = '111';
T1 =设备表,T2 =位置表
<cfif ARGUMENTS.submitButton eq 'btn_Delete'>
<cfquery name="DeleteDevice" datasource="#session.dsn#" maxRows=1 >
DELETE from #session.tq#device
WHERE device_id = <cfqueryparam value="#formStruct.deviceId#" cfsqltype="CF_SQL_VARCHAR">
</cfquery>
</cfif>
<cfif DeleteDevice.RecordCount eq 1>
<cfquery name="DeleteLocation" datasource="#session.dsn#" maxRows=1 >
DELETE from #session.tq#device_location_xref
WHERE device_location_xref_recno=<cfqueryparam value="#formStruct.deviceId#" cfsqltype="CF_SQL_VARCHAR">
</cfquery>
答案 0 :(得分:2)
(我认为将所有有用的评论合并到Community Wiki答案下将很有帮助)
否不适用于SQL Server,否。某些数据库(例如MySQL)支持multi-table delete statements。 SQL Server没有。您将需要多个delete语句。但是,如果目标只是删除记录,那么差别不大。
当前代码无法正常工作的原因有很多。首先,初始delete
查询仅在提交表单后才执行。第二个代码块引用了相同的查询,但没有验证它是否首先存在。如果尚未提交表单,则会导致未定义的变量错误。
第二,更重要的是,以CF的说法,DELETE
语句从不返回“查询”对象。因此,即使第一个查询 did 执行,查询变量DeleteDevice
也不存在。同样,当代码尝试在此处使用它时,将导致未定义的变量错误:<cfif DeleteDevice.RecordCount eq 1>
。
尽管除非有更多内容,否则……cfif
对IMO毫无用处。如果存在有关deviceID的记录,则将其删除。如果没有,什么也不会发生。跳过第二次删除所产生的任何微不足道的节省,都将被增加的代码复杂性所抵消。
最后,尽管它不会导致严重错误,但maxRows=1
并没有按照您的想法进行。它对DELETE
语句没有任何影响,也不会阻止DELETE语句删除多个记录。 maxRows
属性仅适用于返回“查询”对象的语句,并用于限制该查询中包含的记录数。
由于SQL Server不支持多表DELETE
语句,因此您将需要两个语句-无论如何。有几种构造SQL的方法,每种方法各有利弊。但是,在 all 情况下,您应该使用transaction对相关语句进行分组,并确保所有内容作为一个单元完成或失败
多个cfquery的
只需在一个事务中运行两个查询,一个接一个地运行。尽管确实交换了语句顺序,但是为Shawn suggested。由于可能存在FK约束,因此最好先从子/ FK表中删除,然后从主/ PK表中删除。
<cftransaction>
<cfquery datasource="#session.dsn#">
DELETE FROM device_location_xref WHERE ...
</cfquery>
<cfquery datasource="#session.dsn#">
DELETE FROM device WHERE .....
</cfquery>
</cftransaction>
单个cfquery中的多个语句
如JamesAMohler's answer所示,将两个SQL语句都放在一个cfquery标记内是另一种选择。但是,请记住the limitations Alex mentioned。出于安全原因,可以在数据库/驱动程序级别禁用多个语句。因此,这种方法可能不适用于所有环境。
<cftransaction>
<cfquery datasource="#session.dsn#">
DELETE FROM device_location_xref WHERE ...
DELETE FROM device WHERE .....
</cfquery>
</cftransaction>
SQL存储过程
另一个Shawn suggested选项是:将sql逻辑放入存储过程中。一般来说,存储过程更适合复杂的sql操作,并且与cfquery
不同,它们可以返回多个结果集。
CREATE PROCEDURE DeleteDevice
@deviceID VARCHAR(50)
AS
BEGIN
-- minimal error handling for demo only
BEGIN TRAN
DELETE FROM device_location_xref
WHERE device_location_xref_recno = @deviceID
DELETE from device
WHERE device_id = @deviceID
END TRAN
END
然后使用cfstoredproc
而不是cfquery
调用它。
<cfstoredproc procedure="DeleteDevice" datasource="#ds#">
<cfprocparam type="in" value="#formStruct.deviceId#"
cfsqltype="cf_sql_varchar">
</cfstoredproc>
最后,替代项Shawn mentioned是“软删除”。您可以将BIT列添加到表中,而不是实际删除记录。然后,在需要将记录标记为已删除时,UPDATE
将该列标志标记。有关软删除的利弊的讨论,请参见this thread。
UPDATE TableName
SET IsDeleted = 1
WHERE TheIDColumn = 12345
答案 1 :(得分:0)
你能做这样的事吗
<cfquery>
DECLARE @device_id varchar(20) = <cfqueryparam value="#formStruct.deviceId#" cfsqltype="CF_SQL_VARCHAR">
DELETE
FROM T1
WHERE device_id = @device_id
DELETE
FROM T2
WHERE device_id = @device_id
</cfquery>
答案 2 :(得分:0)
我会在一个Windows 10 Professional
语句中从两个表中删除,因为第二次删除不依赖于第一次删除。
cfquery