0

用户收到此错误

诊断:执行数据库查询时出错。[Macromedia][SQLServer JDBC 驱动程序][SQLServer]INSERT 语句中的列多于 VALUES 子句中指定的值。VALUES 子句中的值数必须与 INSERT 语句中指定的列数相匹配。错误发生在第 252 行。消息:执行数据库查询时出错。根本原因:coldfusion.tagext.sql.QueryTag$DatabaseQueryException:执行数据库查询时出错。服务器:server2

应该有大约 60 个值/列。可能的解决方案是添加<CFIF isDefined("VARIABLES.xxx")>每个值,INSERT但这VALUES需要很长时间。有没有更好的办法?这是一些代码

 <CFQUERY name="addAgency" datasource="#REQUEST.dsn#">
    INSERT INTO agency (agency_name, code, address1, address2, city_id, postal, phone, alternativePhone, fax, provincialRegistration,
        <!--- contact, ---> firstname, lastname, username, password, relationship_id, editdate, adddate, email, URL_link,Airport_id,
        header, teaser, full_desc, <CFIF isDefined("VARIABLES.specialty")>specialty,</CFIF> hours_1, hours_2, hours_3, hours_4, 
        hours_5, hours_6, hours_7, merchant_ID,
        region_ID, fcApproved, agencyType_ID, agencystatus, crossview, insp_Approved, rbc_Approved,
        branch_number, gp_entity_ID,
        <CFIF VARIABLES.alias1 gt 100> alias1,</CFIF>
        <CFIF VARIABLES.alias2 gt 100> alias2,</CFIF>
        <CFIF Trim(VARIABLES.alias3) NEQ ""> alias3,</CFIF>
        default_agent_id,LOCAL_PASSWORD,LOCAL_USERNAME,NATIONAL_PASSWORD,NATIONAL_USERNAME,VACATIONCLUB_PASSWORD,VACATIONCLUB_USERNAME,toll_free_number,display_toll_free ,MARKETINGREGIONID, searchPreference, bookingOption,customer_can_choose
        <CFIF isDefined("variables.logo_filedata")>,logo_fileName,logo_fileData,logo_mimeType</CFIF>
        ,gds, pseudo_city, acv_affiliate_code, vip_ext,owner_manager_title_en,owner_manager_title_fr)

    VALUES (<CFQUERYPARAM value="#Trim(sanitize(VARIABLES.agency_name))#"  cfsqltype = "cf_sql_varchar" maxlength="150">, 
        <CFQUERYPARAM value="#Trim(sanitize(VARIABLES.code))#"  cfsqltype = "cf_sql_varchar" maxlength="50">, 
        <CFQUERYPARAM value="#Trim(sanitize(VARIABLES.address1))#"  cfsqltype = "cf_sql_varchar" maxlength="255">,
            <CFQUERYPARAM value="#Trim(sanitize(VARIABLES.address2))#"  cfsqltype = "cf_sql_varchar" maxlength="255">,
            <CFQUERYPARAM value="#sanitize(VARIABLES.city_id,true,true,false,true,false)#"  cfsqltype = "cf_sql_integer">,
            <CFQUERYPARAM value="#Trim(sanitize(VARIABLES.postal))#"  cfsqltype = "cf_sql_varchar" maxlength="10">,
            <CFQUERYPARAM value="#Trim(sanitize(VARIABLES.phone))#"  cfsqltype = "cf_sql_varchar" maxlength="20">,
            <CFQUERYPARAM value="#Trim(sanitize(VARIABLES.fax))#"  cfsqltype = "cf_sql_varchar" maxlength="20">,    
        <!--- <CFIF IsDefined("VARIABLES.contact")>#Trim(VARIABLES.contact)#, <CFELSE> ' ', </CFIF> --->
            <CFQUERYPARAM value="#Trim(sanitize(VARIABLES.firstname))#"  cfsqltype = "cf_sql_varchar" maxlength="40">,
            <CFQUERYPARAM value="#Trim(sanitize(VARIABLES.lastname))#"  cfsqltype = "cf_sql_varchar" maxlength="40">,
            '-', '-',   
        <!--- Dummy un/pw --->
            <CFQUERYPARAM value="#sanitize(VARIABLES.relationship_ID,true,true,false,true,false)#"  cfsqltype = "cf_sql_integer">,
            #CreateODBCDateTime(Now())#,
        #CreateODBCDateTime(Now())#,
            <CFQUERYPARAM value="#Trim(sanitize(VARIABLES.email))#" cfsqltype = "cf_sql_varchar" maxlength="40">,
4

3 回答 3

4

只要您这样做,“列”区域中的每个 s 都必须与“值”部分中的推论 CFIF 匹配。虽然还有其他方法可以做到这一点,但它们不一定不那么混乱。例如,您可以:

  1. 使用一些 cfparams 为所有列设置默认值,因此您不必有任何“cfifs”
  2. 编写多个“更干净”的查询
  3. 将整个事情移动到一个存储过程并将你拥有的东西传递给它——然后 SP 会担心逻辑。
  4. 保存一小部分值,然后根据您的 cfif 逻辑“更新”(不喜欢那个!)。

如您所见,它们都有缺点。


详述 1)

而不是做一些艰苦的事情,比如:

<CFIF isDefined("VARIABLES.specialty")> Specialty,</cfif>

在开始查询之前,请确保您拥有使用 cfparam 所需的所有变量的值,如下所示:

<Cfparam name="Specialty" default=""/>

(当然,专业的默认值可能是 0 或其他)。

cfparam 标记检查变量是否存在,如果存在,则使用您指定的默认值创建它。这意味着您可以“保证”该变量确实存在 - 这意味着您可以消除查询中的 CFIF 语句。

一个注意事项与数据库中的 NULL 有关。如果您依赖于空值(意味着如果不存在您希望该列保持空值的专业),那么您需要将“null”属性添加到您的 cfqueryparam 中,如下所示:

<CFQUERYPARAM 
  value="#Trim(sanitize(VARIABLES.specialty))#" 
  cfsqltype = "cf_sql_varchar" 
  null="#mynullfunction(variables.specialty)#"/>,

请注意“mynullfunction”——我通常为此创建一个实用程序 UDF,如果该值为空白或零(或我定义的任何值),则仅返回 YES,如果已填充,则返回“no”。

于 2012-07-03T22:09:48.843 回答
1

最好的解决方案是对数据库中未设置默认值的列使用 cfqueryparam 的 null 属性,这意味着您可以避免向 INSERT INTO 添加条件并将 VALUE 保持为每列一行。当列确实存在默认值时,您需要使用冗长的条件。这是最简单、最不显眼的更改。

Alias1 具有数据库默认值的示例,specialty 没有。

`   <cfset Variables.IsValidAlias1 = Variables.alias1 gt 100> 
    <cfquery name="addAgency" datasource="#REQUEST.dsn#">
        INSERT INTO agency (agency_name, 
                            specialty
                            <cfif Variables.IsValidAlias1>
                            , Alias1
                            </cfif>)
        VALUES (<cfqueryparam value="#Variables.agency_name#" cfsqltype="cf_sql_varchar" maxlength="150">, 
                <cfqueryparam value="#Variables.specialty#" cfsqltype="cf_sql_varchar" null="#StructKeyExists(Variables,'Specialty') EQ false#" maxlength="199">
                <cfif Variables.IsValidAlias1>
                    ,<cfqueryparam value="#Variables.Alias1#" cfsqltype="cf_sql_varchar" maxlength="199">
                </cfif>)
     </cfquery>`

顺便说一句,您应该使用 StructKeyExists() 而不是 IsDefined,因为前者更快并且更易于阅读。您应该将此代码放在一个函数中,并将该函数放在一个组件中,以便可以重用。这是假设您使用 CF6 或更高版本。

于 2012-07-04T14:50:56.763 回答
0

我会避免为每个字段设置空字符串默认值或将不存在的键的值设置为 NULL。原因是您现在(或决定将来)数据库列中的默认值。由于生成的 NULL 值是显式的,它们将覆盖您的数据库默认值。如果您传入了一个空字符串,这可能是有效的,但默认情况下可能不是。

我的主要建议是将每一列保持在一行,以便您轻松看到您在条件句中的一致性。正如马克所说,您必须小心在“列”区域中使用与查询的“值”区域完全相同的条件。

顺便说一句,我有一个名为 DataMgr 的免费工具,您可以使用它来管理大多数简单查询的所有此类事情。

http://www.bryantwebconsulting.com/docs/datamgr/replace-sql-inserts-and-updates.cfm http://www.bryantwebconsulting.com/docs/datamgr/getting-started.cfm

然而,最重要的是要在您的条件句中保持一致,并以这样一种方式格式化您的查询,以便在您不符合条件时使其显而易见。

于 2012-07-04T16:18:47.887 回答