修复“插入中的列多于指定的值”

时间:2012-07-03 21:26:23

标签: sql database coldfusion

用户收到此错误

  

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

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

 <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">,

3 个答案:

答案 0 :(得分:4)

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

  1. 为所有列设置默认值并使用一些cfparams,这样您就不必拥有任何“cfifs”
  2. 撰写多个“清洁”查询
  3. 将整个内容移动到存储过程并将所有内容传递给它 - 然后SP会担心逻辑。
  4. 保存一小部分值,然后根据您的cfif逻辑“更新”(不喜欢那个!)。
  5. 正如你所看到的,它们都有缺点。


    详细阐述1)

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

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

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

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

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

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

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

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

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

答案 1 :(得分:1)

最好的解决方案是将cfqueryparam的null属性用于未在数据库中设置默认值的列,这意味着您可以避免向INSERT INTO添加条件并将VALUE保持为每列一行。如果列存在默认值,则需要使用long winded条件。这是最简单,最不突兀的变化。

Alias1具有数据库默认值的示例,特殊情况不是。

`   <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或更高版本。

答案 2 :(得分: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

然而,最重要的是要保持条件的一致性并格式化查询,以便在不存在时使其显而易见。