如何从一个.cfc文件的一个DELETE语句中的多个表中删除?

时间:2019-05-31 03:41:07

标签: sql-server tsql coldfusion

我有两个桌子。设备表和位置表。设备表中只能有一个设备,但是位置表中可以有多个具有多个位置的设备。

如果用户删除设备,我还需要从位置表中删除具有相同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>

3 个答案:

答案 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