【问题标题】:PHP MS SQL Invalid parameter number: number of bound variables does not match number of tokensPHP MS SQL 参数号无效:绑定变量的数量与标记的数量不匹配
【发布时间】:2013-06-21 09:43:30
【问题描述】:

我正在尝试从我的 MS SQL 数据库运行存储过程。存储过程来自汽车配件商店的 POS(销售点系统)数据库 - 因此该过程编写正确,并且已被证明可以与 POS 系统一起使用。

尝试运行此存储过程时,我不断收到错误 - SQLSTATE[HY093] - 无效参数号:超出范围的变量数与令牌数不匹配。

这是我的 PHP 代码

$db = new PDO($dsn, $user, $password);

$stmt = $db->prepare("CALL insertworkorder(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); ");

$WorkOrderID = 4;
$StoreNumber = 4;
$YardNumber = 4;
$WorkOrderNumber = 3;
$EstimateNumber = '4';
$AccountNumber = 4;
$CustomerNumber = 4;
$CreatedBy = 5;
$DeliveryDate = 4332;
$BillToBusinessName = 'example';
$BillToContactName = 'example';
$BillToAttentionLine = 'example';
$BillToAddress1 = 'example';
$BillToAddress2 = 'example';
$BillToCity = 'example';
$BillToCounty = 'example';
$BillToStateOrProvince = 'example';
$BillToPostalCode = 'example';
$BillToCountry = 'USA';
$BillToContactFAX = 5466;
$BillToContactPhone = example;
$BillToContactOtherPhone = v; 
$BillToContactEMail = 'example@example.net';
$ShipToBusinessName = 'example';
$ShipToContactName = 'example';
$ShipToAttentionLine = 'example';
$ShipToAddress1 = 'example';
$ShipToAddress2 = 'example';
$ShipToCity = 'example';
$ShipToCounty = 'USA';
$ShipToStateOrProvince = 'CT';
$ShipToPostalCode = 'example';
$ShipToCountry = 'USA';
$ShipToContactFax = 'example';
$ShipToContactPhone = 'example';
$ShipToContactOtherPhone = 'example';
$ShipToContactEMail = '';
$ShipVIA = '22';
$CustomerPO = '22';
$WorkOrderStatus = '22';
$WorkOrderNotes = '2';
$Amount = '2';
$TotalDiscountAmount = '2';
$TotalFreightAmount = '2';
$ApplyCustomerTaxRate = '22';
$TotalFreightTaxAmount = '22';
$FreightIsTaxable = '2';
$GSTTaxExempt = '22';
$TotalPartsAmount = '22';
$TotalServicesAmount = '22';
$TotalCoreAmount = '';
$TotalLineItemTaxAmount = '22';
$OrderSource = 'website';
$TrackingNumber = '1226412258223';
$ReasonForVoid = '2';
$EComRequestID = 22;
$CurrentUserID = 22;
$PaypalTransactionID = '3';
$TaxExemptID = '3';
$LegalTraceID = '3';
$BillToContactPhoneExt = '3';
$BillToContactOtherPhoneExt = '3';
$ShipToContactPhoneExt = '3';
$ShipToContactOtherPhoneExt = '3';


$stmt->bindValue(':@StoreNumber', $StoreNumber, PDO::PARAM_INT); //REQUIRED
$stmt->bindValue(':@YardNumber', $YardNumber, PDO::PARAM_INT); //REQUIRED
$stmt->bindValue(':@EstimateNumber', $EstimateNumber, PDO::PARAM_STR);
$stmt->bindValue(':@AccountNumber', $AccountNumber, PDO::PARAM_INT); //REQUIRED
$stmt->bindValue(':@CustomerNumber', $CustomerNumber, PDO::PARAM_INT); //REQUIRED
$stmt->bindValue(':@CreatedBy', $CreatedBy, PDO::PARAM_INT); //REQUIRED
$stmt->bindValue(':@DeliveryDate', $DeliveryDate, PDO::PARAM_INT);
$stmt->bindValue(':@BillToBusinessName ', $BillToBusinessName, PDO::PARAM_STR);
$stmt->bindValue(':@BillToContactName', $BillToContactName, PDO::PARAM_INT);
$stmt->bindValue(':@BillToAttentionLine ', $BillToAttentionLine , PDO::PARAM_STR);
$stmt->bindValue(':@BillToAddress1', $BillToAddress1, PDO::PARAM_STR);
$stmt->bindValue(':@BillToAddress2 ', $BillToAddress2 , PDO::PARAM_STR);
$stmt->bindValue(':@BillToCity', $BillToCity, PDO::PARAM_STR);
$stmt->bindValue(':@BillToCounty', $BillToCounty, PDO::PARAM_STR);
$stmt->bindValue(':@BillToStateOrProvince', $BillToStateOrProvince, PDO::PARAM_STR);
$stmt->bindValue(':@BillToPostalCode', $BillToPostalCode, PDO::PARAM_STR);
$stmt->bindValue(':@BillToCountry', $BillToCountry, PDO::PARAM_STR);
$stmt->bindValue(':@BillToContactFAX', $BillToContactFAX, PDO::PARAM_STR);
$stmt->bindValue(':@BillToContactPhone', $BillToContactPhone, PDO::PARAM_STR);
$stmt->bindValue(':B@illToContactOtherPhone', $BillToContactOtherPhone, PDO::PARAM_STR);
$stmt->bindValue(':@BillToContactEMail', $BillToContactEMail, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToBusinessName', $ShipToBusinessName, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToContactName', $ShipToContactName, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToAttentionLine', $ShipToAttentionLine, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToAddress1', $ShipToAddress1, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToAddress2', $ShipToAddress2, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToCity', $ShipToCity, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToCounty', $ShipToCounty, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToStateOrProvince', $ShipToStateOrProvince, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToPostalCode', $ShipToPostalCode, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToCountry', $ShipToCountry, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToContactFax', $ShipToContactFax, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToContactPhone', $ShipToContactPhone, PDO::PARAM_STR);
$stmt->bindValue(':@ToContactOtherPhone', $ShipToContactOtherPhone, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToContactEMail', $ShipToContactEMail, PDO::PARAM_STR);
$stmt->bindValue(':@ShipVIA', $ShipVIA, PDO::PARAM_STR);
$stmt->bindValue(':@CustomerPO', $CustomerPO, PDO::PARAM_STR);
$stmt->bindValue(':@WorkOrderStatus', $WorkOrderStatus, PDO::PARAM_STR);
$stmt->bindValue(':@WorkOrderNotes', $WorkOrderNotes, PDO::PARAM_STR);
$stmt->bindValue(':@Amount', $Amount, PDO::PARAM_STR); //REQUIRED
$stmt->bindValue(':@TotalDiscountAmount', $TotalDiscountAmount, PDO::PARAM_STR); //REQUIRED
$stmt->bindValue(':@TotalFreightAmount', $TotalFreightAmount, PDO::PARAM_STR);
$stmt->bindValue(':@ApplyCustomerTaxRate', $ApplyCustomerTaxRate, PDO::PARAM_STR); //REQUIRED
$stmt->bindValue(':@TotalFreightTaxAmount', $TotalFreightTaxAmount, PDO::PARAM_STR); //REQUIRED
$stmt->bindValue(':@FreightIsTaxable', $FreightIsTaxable, PDO::PARAM_BOOL); //REQUIRED
$stmt->bindValue(':@GSTTaxExempt', $GSTTaxExempt, PDO::PARAM_BOOL); //REQUIRED
$stmt->bindValue(':@TotalPartsAmount', $TotalPartsAmount, PDO::PARAM_STR);
$stmt->bindValue(':@TotalServicesAmount', $TotalServicesAmount, PDO::PARAM_STR); //REQUIRED
$stmt->bindValue(':@TotalCoreAmount', $TotalCoreAmount, PDO::PARAM_STR);
$stmt->bindValue(':@TotalLineItemTaxAmount', $TotalLineItemTaxAmount, PDO::PARAM_STR);
$stmt->bindValue(':@OrderSource', $OrderSource, PDO::PARAM_STR);
$stmt->bindValue(':@TrackingNumber', $TrackingNumber, PDO::PARAM_STR);
$stmt->bindValue(':@ReasonForVoid', $ReasonForVoid, PDO::PARAM_STR);
$stmt->bindValue(':@EComRequestID', $EComRequestID, PDO::PARAM_INT);
$stmt->bindValue(':@CurrentUserID', $CurrentUserID, PDO::PARAM_INT);
$stmt->bindValue(':@PaypalTransactionID', $PaypalTransactionID, PDO::PARAM_STR);
$stmt->bindValue(':@TaxExemptID', $TaxExemptID, PDO::PARAM_STR);
$stmt->bindValue(':@LegalTraceID', $LegalTraceID, PDO::PARAM_STR);
$stmt->bindValue(':@BillToContactPhoneExt', $BillToContactPhoneExt, PDO::PARAM_STR);
$stmt->bindValue(':@BillToContactOtherPhoneExt', $BillToContactOtherPhoneExt, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToContactPhoneExt', $ShipToContactPhoneExt, PDO::PARAM_STR);
$stmt->bindValue(':@ShipToContactOtherPhoneExt', $ShipToContactOtherPhoneExt, PDO::PARAM_STR);
$stmt->bindParam(':@WorkOrderID', $WorkOrderID, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT);
$stmt->bindParam(':@WorkOrderNumber', $WorkOrderNumber, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT);

$result = $stmt->execute();

print_r($stmt->errorInfo());

这是sql过程:

ALTER procedure [dbo].[insertworkorder]
    (
    @StoreNumber                int,
    @YardNumber                 int,
    @EstimateNumber             varchar(20),
    @AccountNumber              accountnumber,
    @CustomerNumber             customernumber,
    @CreatedBy                  int,
    @DeliveryDate               datetime,
    @BillToBusinessName         contactlong,
    @BillToContactName          contactlong,
    @BillToAttentionLine        contactlong,
    @BillToAddress1             AddressLong,
    @BillToAddress2             AddressLong,
    @BillToCity                 CityLong,
    @BillToCounty               varchar(25),
    @BillToStateOrProvince      stateorprovince,
    @BillToPostalCode           postalcode,
    @BillToCountry              country,
    @BillToContactFAX           phonenumber,
    @BillToContactPhone         phonenumber,
    @BillToContactOtherPhone    phonenumber,
    @BillToContactEMail         email,
    @ShipToBusinessName         contactlong,
    @ShipToContactName          contactlong,
    @ShipToAttentionLine        contactlong,
    @ShipToAddress1             AddressLong,
    @ShipToAddress2             AddressLong,
    @ShipToCity                 CityLong,
    @ShipToCounty               varchar(25),
    @ShipToStateOrProvince      stateorprovince,
    @ShipToPostalCode           postalcode,
    @ShipToCountry              country,
    @ShipToContactFax           phonenumber,
    @ShipToContactPhone         phonenumber,
    @ShipToContactOtherPhone    phonenumber,
    @ShipToContactEMail         email,
    @ShipVIA                    varchar(20),
    @CustomerPO                 varchar(20),
    @WorkOrderStatus            status,
    @WorkOrderNotes             notes,
    @Amount                     money,
    @TotalDiscountAmount        money,
    @TotalFreightAmount         money,
    @ApplyCustomerTaxRate       boolean,
    @TotalFreightTaxAmount      money,
    @FreightIsTaxable           boolean,
    @GSTTaxExempt               boolean,
    @TotalPartsAmount           money,
    @TotalServicesAmount        money,
    @TotalCoreAmount            money,
    @TotalLineItemTaxAmount     money,
    @OrderSource                char(1),
    @TrackingNumber             varchar(50),
    @ReasonForVoid              varchar(255),
    @EComRequestID              int,
    @CurrentUserID              int,
    @PaypalTransactionID        varchar(30),
    @TaxExemptID                varchar(24),
    @LegalTraceID               varchar(24),
    @BillToContactPhoneExt      PhoneExt,
    @BillToContactOtherPhoneExt PhoneExt,
    @ShipToContactPhoneExt      PhoneExt,
    @ShipToContactOtherPhoneExt PhoneExt,
    @WorkOrderID                int output,
    @WorkOrderNumber            int output
    )
as

    set nocount on

    exec dbo.getnextcounter 'WORKORDER', 'WorkOrderID', @WorkOrderID output
    exec dbo.getnexttransactioncounter @YardNumber, @StoreNumber, 'WORKORDER', 'WorkOrderNumber', @WorkOrderNumber output



    insert dbo.WORKORDER
        (
        WorkOrderID,
        StoreNumber,
        Revision,
        YardNumber,
        WorkOrderNumber,
        EstimateNumber,
        AccountNumber,
        CustomerNumber,
        CreatedBy,
        DeliveryDate,
        DateCreated,
        BillToBusinessName,
        BillToContactName,
        BillToAttentionLine,
        BillToAddress1,
        BillToAddress2,
        BillToCity,
        BillToCounty,
        BillToStateOrProvince,
        BillToPostalCode,
        BillToCountry,
        BillToContactFAX,
        BillToContactPhone,
        BillToContactOtherPhone,
        BillToContactEMail,
        ShipToBusinessName,
        ShipToContactName,
        ShipToAttentionLine,
        ShipToAddress1,
        ShipToAddress2,
        ShipToCity,
        ShipToCounty,
        ShipToStateOrProvince,
        ShipToPostalCode,
        ShipToCountry,
        ShipToContactFax,
        ShipToContactPhone,
        ShipToContactOtherPhone,
        ShipToContactEMail,
        ShipVIA,
        CustomerPO,
        WorkOrderStatus,
        WorkOrderNotes,
        Amount,
        TotalDiscountAmount,
        TotalFreightAmount,
        ApplyCustomerTaxRate,
        TotalFreightTaxAmount,
        FreightIsTaxable,
        GSTTaxExempt,
        TotalPartsAmount,
        TotalServicesAmount,
        TotalCoreAmount,
        TotalLineItemTaxAmount,
        OrderSource,
        TrackingNumber,
        ReasonForVoid,
        EComRequestID,
        IsLastRevision,
        CurrentUserID,
        PaypalTransactionID,
        TaxExemptID,
        LegalTraceID,
        BillToContactPhoneExt,
        BillToContactOtherPhoneExt,
        ShipToContactPhoneExt,
        ShipToContactOtherPhoneExt
        )

    values
        (
        @WorkOrderID,
        @StoreNumber,
        0,                      /* Revision         */
        @YardNumber,
        @WorkOrderNumber,
        @EstimateNumber,
        @AccountNumber,
        @CustomerNumber,
        @CreatedBy,
        @DeliveryDate,
        getdate(),              /* @DateCreated     */
        @BillToBusinessName,
        @BillToContactName,
        @BillToAttentionLine,
        @BillToAddress1,
        @BillToAddress2,
        @BillToCity,
        @BillToCounty,
        @BillToStateOrProvince,
        @BillToPostalCode,
        @BillToCountry,
        @BillToContactFAX,
        @BillToContactPhone,
        @BillToContactOtherPhone,
        @BillToContactEMail,
        @ShipToBusinessName,
        @ShipToContactName,
        @ShipToAttentionLine,
        @ShipToAddress1,
        @ShipToAddress2,
        @ShipToCity,
        @ShipToCounty,
        @ShipToStateOrProvince,
        @ShipToPostalCode,
        @ShipToCountry,
        @ShipToContactFax,
        @ShipToContactPhone,
        @ShipToContactOtherPhone,
        @ShipToContactEMail,
        @ShipVIA,
        @CustomerPO,
        @WorkOrderStatus,
        @WorkOrderNotes,
        @Amount,
        @TotalDiscountAmount,
        @TotalFreightAmount,
        @ApplyCustomerTaxRate,
        @TotalFreightTaxAmount,
        @FreightIsTaxable,
        @GSTTaxExempt,
        @TotalPartsAmount,
        @TotalServicesAmount,
        @TotalCoreAmount,
        @TotalLineItemTaxAmount,
        @OrderSource,
        @TrackingNumber,
        @ReasonForVoid,
        @EComRequestID,
        1,
        @CurrentUserID,                       /* IsLastRevision   */
        @PaypalTransactionID,
        @TaxExemptID,
        @LegalTraceID,
        @BillToContactPhoneExt,
        @BillToContactOtherPhoneExt,
        @ShipToContactPhoneExt,
        @ShipToContactOtherPhoneExt
        )

    set nocount off

    return (0)

感谢您的帮助!!

瓦斯

【问题讨论】:

  • 你从哪里得到:@StoreNumber 语法?您正在学习什么 PDO 教程?
  • @StoreNumber 来自提供给我的 SQL 过程。该程序之所以有效,是因为它被汽车零部件商店使用的销售点系统使用。
  • 但这不是您在此处调用的过程,而是 PDO 语句的绑定参数
  • 我正在为 SQL 过程绑定值,所以我可以传入我存储在上述变量中​​的值,这样我就可以从过程中获取返回值。我已经更改了 bindValue() 函数 $stmt->bindValue(1, $StoreNumber, PDO::PARAM_INT);

标签: php sql sql-server pdo odbc


【解决方案1】:

你有两个主要问题。 1) 您的查询使用问号占位符,您的 ->bindValue 函数使用命名参数。 2)你只有 20 个问号,你试图绑定大约 60 个值(我停止数大约 40 个)。

如果你想使用命名参数,你需要像这样编写代码:

$stmt = $db->prepare("CALL insertworkorder(:StoreNumber, :YardNumber, ... etc ... ");

$stmt->bindValue(':StoreNumber', $StoreNumber, PDO::PARAM_INT); //REQUIRED
$stmt->bindValue(':YardNumber', $YardNumber, PDO::PARAM_INT);
// ... etc ...

如果你想使用问号占位符,你可以这样做:

$stmt = $db->prepare("CALL insertworkorder(?, ?, ?, ... etc ...");

$stmt->bindValue(1, $StoreNumber, PDO::PARAM_INT);
$stmt->bindValue(2, $YardNumber, PDO::PARAM_INT);
// ... etc ...

您必须确保您拥有与问号(或命名参数)相同数量的 bindValues,否则您将收到 Invalid Parameter number: number out of bound variables does not match number of tokens. 错误

【讨论】:

  • 我已经编辑了我的脚本以获得正确的问号数量,并且我已经正确地对 bindValue() 函数进行了编号,如您在上面举例说明的,感谢您到目前为止的帮助。但我现在收到此错误 HY000 [1] => 102 [2] => 一般 SQL Server 错误:检查来自 SQL Server [102](严重性 15)[(null)]的消息
【解决方案2】:

嘿,我知道这是一篇旧帖子 - 但只是关于我在哪里结束的更新。

在我花了几个小时(另一名员工也花了几个小时尝试)之后,我们决定 Microsoft Sql 存储过程不能与使用 PDO 连接器的 PHP 一起工作。

我们最终在 PHP 中创建了一个导出功能,将所有内容转储到 XML 文件中,然后我们开发了一个 Java 程序,该程序在 CRON 中每分钟运行一次,扫描我们的文件夹中的 XML 文件并使用 JDBC 驱动程序执行 Ms SQL 存储过程传入从 XML 文件中读取的内容,然后删除 XML 文件...

不确定他们是否已解决此问题,但根据我的经验 PHP 不适用于 Microsoft SQL 存储过程

干杯

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多