ColdFusion 在执行数据库查询时出错

ColdFusion is giving error when executing database query

有人可以建议这段代码有什么问题吗?

<cfquery name="getPreviousDBentries" datasource="#application.datasource#">
    select image, image_b,
    image_c,image_d,image_e, image_f from used_listings_v2 where id = '#edit#'
</cfquery>

<cfdump var="#getPreviousDBentries#">
<cftry>
    <cfquery name="updateToNull" datasource="#application.datasource#">
        <cfif len(getPreviousDBentries.image) neq 0>
            Update used_listings_v2 SET image = NULL where id = '#edit#'
        </cfif>

        <cfif len(getPreviousDBentries.image_b) neq 0>
            Update used_listings_v2 SET image_b = NULL where id = '#edit#'
        </cfif>

        <cfif len(getPreviousDBentries.image_c) neq 0>
            Update used_listings_v2 SET image_c = NULL where id = '#edit#'
        </cfif>

        <cfif len(getPreviousDBentries.image_d) neq 0>
            Update used_listings_v2 SET image_d = NULL where id = '#edit#'
        </cfif>

        <cfif len(getPreviousDBentries.image_e) neq 0>
            Update used_listings_v2 SET image_e = NULL where id = '#edit#'
        </cfif>

        <cfif len(getPreviousDBentries.image_f) neq 0>
            Update used_listings_v2 SET image_f = NULL where id = '#edit#'
        </cfif>
    </cfquery>

<cfcatch>
<cfdump var="#cfcatch#">
</cfcatch>

</cftry>

当 image 列有一些值时,我得到正确的输出,即 image、image_b、image_c、image_d、image_e、image_f 是不为空。

但是当图像 image_b、image_c、image_d、image_e、image_f 为 null 时,它会提示我执行数据库查询时出错.

请提出可能的解决方案。

您收到错误消息的原因是因为所有 <cfif> 条件都为假,这就像执行 <cfquery> 而其中没有代码。因此,您需要在 <cfquery> 块之外添加一个附加条件来测试并确保至少执行一个 UPDATE 命令。

<cfquery name="getPreviousDBentries" datasource="#application.datasource#">
    select image, image_b,
    image_c,image_d,image_e, image_f from used_listings_v2 where id = '#edit#'
</cfquery>

<cfif NOT (len(getPreviousDBentries.image) eq 0> AND 
      len(getPreviousDBentries.image_b) eq 0 AND
      len(getPreviousDBentries.image_c) eq 0 AND
      len(getPreviousDBentries.image_d) eq 0 AND
      len(getPreviousDBentries.image_e) eq 0 AND
      len(getPreviousDBentries.image_f) eq 0)>

    <cftry>
        <cfquery name="updateToNull" datasource="#application.datasource#">
            <cfif len(getPreviousDBentries.image) neq 0>
                Update used_listings_v2 SET image = NULL where id = '#edit#'
            </cfif>

            <cfif len(getPreviousDBentries.image_b) neq 0>
                Update used_listings_v2 SET image_b = NULL where id = '#edit#'
            </cfif>

            <cfif len(getPreviousDBentries.image_c) neq 0>
                Update used_listings_v2 SET image_c = NULL where id = '#edit#'
            </cfif>

            <cfif len(getPreviousDBentries.image_d) neq 0>
                Update used_listings_v2 SET image_d = NULL where id = '#edit#'
            </cfif>

            <cfif len(getPreviousDBentries.image_e) neq 0>
                Update used_listings_v2 SET image_e = NULL where id = '#edit#'
            </cfif>

            <cfif len(getPreviousDBentries.image_f) neq 0>
                Update used_listings_v2 SET image_f = NULL where id = '#edit#'
            </cfif>
        </cfquery>

        <cfcatch>
            <cfdump var="#cfcatch#">
        </cfcatch>

    </cftry>
</cfif>

already explains why the error occurs. As far as the code, instead of constructing multiple queries, a single query would be more maintainable. Use a CASE statement or your database's version of IIF 仅在值为空时更新列。确切的语法是特定于 dbms 的。

例如,假设除了“image_d”之外所有图像列都已填充:

示例

id  | image     | image_b    | image_c  | image_d
1   | arrow.png | up.png     | down.png | (empty string)    

DDL(SQL 服务器)

CREATE TABLE used_listings_v2 
(
   id int 
   , image varchar(50)
   , image_b varchar(50)
   , image_c varchar(50)
   , image_d varchar(50)
)
;


INSERT INTO used_listings_v2 (id, image, image_b, image_c, image_d)
VALUES (1, 'arrow.png', 'up.png', 'down.png', '')
;

使用 CASE 检查现有值的长度,仅当包含空字符串(即长度 = 0)时才将它们设置为 NULL。

-- Example using CASE
SET Column = CASE WHEN LEN(Column) = 0 THEN NULL ELSE Column END

-- Example using IIF
SET Column = IIF( LEN(Column) = 0, NULL, Column ) 

因此此查询将保留任何现有值并且仅将空列更新为空:

SQL Fiddle

UPDATE used_listings_v2
SET    image = CASE WHEN LEN(image) = 0 THEN NULL ELSE image END
       , image_b = CASE WHEN LEN(image_b) = 0 THEN NULL ELSE image_b END
       , image_c = CASE WHEN LEN(image_c) = 0 THEN NULL ELSE image_c END
       , image_d = CASE WHEN LEN(image_d) = 0 THEN NULL ELSE image_d END
WHERE id = 1

结果

id  | image     | image_b    | image_c  | image_d
1   | arrow.png | up.png     | down.png | (null)    

注意:在实际的 cfquery 中,将 #edit# 变量包装在 cfqueryparam 中以帮助保护查询免受 sql 注入。

尽管如此,拥有一堆名称相似的列都存储相同的东西(即图像、image_b、image_c、..、image_N)是 一个您需要 normalize the model. 而不是列的强大指标,它提供了更大的灵活性并且会简化这样的任务。