PDO 不能在 Access 数据库中插入新记录,但可以在同一个连接中读取和删除

Posted

技术标签:

【中文标题】PDO 不能在 Access 数据库中插入新记录,但可以在同一个连接中读取和删除【英文标题】:PDO can't insert new record into Access database, but can read and delete in same connection 【发布时间】:2014-08-19 11:49:29 【问题描述】:

我有问题。我有一个 ms Access 数据库文件,我必须阅读和修改(删除和插入记录)。我使用 PDO odbc。而且我有一种奇怪的情况,我可以读取和删除,但我无法在具有相同连接的数据库中插入新记录。 我已经在 ms Access 中检查了插入字符串,它运行良好。 这里是php代码:

<?php

$path = getcwd() . "\\tempFolder\\MSDB.mdb";
$con = "odbc:DRIVER=Microsoft Access Driver (*.mdb); DBQ=$path; Uid=; Pwd=;";
try

    $db = new PDO($con);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    //READ
    $cmd = "SELECT * FROM temp_HEADER WHERE [LINE-ID]='101'";
    $result = $db->prepare($cmd);
    $result->execute();
    $result = $result->fetch(PDO::FETCH_ASSOC);
    print_r($result); echo "<br/>";

    //DELETE
    $cmd = "DELETE FROM temp_HEADER WHERE [LINE-ID]='101'";
    $result = $db->prepare($cmd);
    $result->execute();
    echo "DELETE OK<br/>";

    //INSERT
    $cmd = "INSERT INTO temp_HEADER ([LINE-ID], PLANE, DISPLAY, X, Y, Z, LENGTH, SURF, ROCK, VARIA, LTYPE, NAME) "
    . "VALUES('101', '100', '', 100, 100, 100, 0, 0, '', 1, 'LINE', 'TEMP')";
    $result = $db->prepare($cmd);
    $result->execute();    
    echo "INSERT OK";

 catch (Exception $ex) 
    echo $ex->getMessage();

这段代码让我得到以下结果:

Array ( [LINE-ID] => 101 [PLANE] => 100 [DISPLAY] => [X] => 100.0 [Y] => 100.0 [Z] => 100.0 [LENGTH] => 0.0 [SURF] => 0.0 [ROCK] => [VAR] => 1 [LTYPE] => LINE [NAME] => TEMP [Ind] => 1041 ) 
DELETE OK
SQLSTATE[22018]: Invalid character value for cast specification: 39 [Microsoft][Driver ODBC Microsoft Access]Invalid character value for cast specification (null) (SQLExecute[39] at ext\pdo_odbc\odbc_stmt.c:254)

这有什么问题? p.s.:我在几台计算机上测试了这个脚本,其中一些很好地显示了所有结果,但另一个 - 在插入命令中出错。 编辑:添加字段类型:

LINE-ID - Text<br/>
PLANE - Text<br/>
DISPLAY - Text<br/>
X - Number(Double)<br/>
Y - Number(Double)<br/>
Z - Number(Double)<br/>
LENGTH - Number(Double)<br/>
SURF - Number(Double)<br/>
ROCK - Text<br/>
VARIA - Number(Long Integer)<br/>
LTYPE - Text<br/>
NAME - Text<br/>
Ind - AutoNumber(Long Integer)<br/>

编辑:我刚刚用 C# 编写了相同的代码,一切正常(我可以读取、删除和插入)。我使用了与这里相同的 sql 查询,但我使用了 oleDB。在这种情况下,我认为 odbc 与 php 中的 pdo 有问题。有人不能告诉我如何通过 oleDB 在 php 中连接到 DB,因为快速搜索没有得到任何结果? 编辑:我尝试将代码与 COM (OleDB) 一起使用。我用读取、删除和插入重复了相同的任务。我得到了什么:

variant Object 
DELETE OK
Source: Microsoft JET Database Engine
Description: type Mismatch

编辑: 我创建了具有读取、删除和插入功能的 mdb 文件和简单脚本,并将其放入 here。这段代码对我不起作用。如果您可以毫无问题地运行它,请记下您的驱动程序的版本。我认为是驱动程序的问题。就我而言,我已经尝试将 ODBC 快捷方式从 system32 更改为 sysWOW64,但没有任何改变。

【问题讨论】:

无论如何,我无法重现您的问题。我使用所需的表创建了一个测试 .mdb,将您的 PDO 代码复制并粘贴到一个 .php 文件中,它在 PHP 5.4.17 下运行良好。尽管您的示例代码说了什么,但您不会碰巧尝试将 Unicode 字符插入数据库,对吗? 是的,我有 unicode 文本。这个数据库来自另一个软件,我想为我的解决方案进行***修改。我尝试了另一个数据库,一切都可以使用 PDO,但是使用这种文件 - 我遇到了这些麻烦。 我在测试 OLEDB 代码时使用的 .mdb 文件(在下面的回答中)可供下载 here。试试它而不是你的 MSDB.mdb,看看它是否更适合你。 问题是我从另一个程序中获得的这种文件,我必须修改一些东西。我知道这些 mdb-s 有点奇怪,但我必须使用它们。当然,今天早上我创建了自己的 mdb 文件,并执行了 select、delete、update 和 insert 命令,所有这些都执行得很好。 你能复制一个“奇怪的”.mdb 文件,删除所有表中的所有记录,然后将那个“空壳”数据库上传到像wikisend.com 这样的网站吗?所以我们可以尝试重现您的问题? 【参考方案1】:

根据这个list,var是MS Access中的保留字。

您的一个变量名为var,因此您遇到了语法错误。将名称用方括号括起来。

编辑:

该错误表明其中一列与您提供的值之间存在类型冲突。无论如何,最重要的想法是相同的。连接很好。 SQL 有语法错误。

【讨论】:

我只为这里制作了较短的字符串。在原始变量中...单词【参考方案2】:

“显示”字段是什么类型。您似乎将其插入数据库,但打印输出显示它是一个二维数组

【讨论】:

我在上面添加了字段类型【参考方案3】:

如何在 php 中通过 oleDB 连接到数据库

要通过 OLEDB 执行 INSERT,您可以使用类似这样的方法

<?php
// this code requires the following php.ini directive:
//
// extension=php_com_dotnet.dll

$path = getcwd() . "\\tempFolder\\MSDB.mdb";
$con = new COM("ADODB.Connection"); 
$con->Open(
        "Provider=Microsoft.Jet.OLEDB.4.0;" .
        "Data Source=$path");

$cmd = "INSERT INTO temp_HEADER ([LINE-ID], PLANE, DISPLAY, X, Y, Z, LENGTH, SURF, ROCK, VARIA, LTYPE, NAME) "
    . "VALUES('101', '100', '', 100, 100, 100, 0, 0, '', 1, 'LINE', 'TEMP')";       

$con->Execute($cmd);

$con->Close();

如果您正在处理 Unicode 文本(正如您在问题的 cmets 中提到的那样),那么我强烈建议您放弃 PDO_ODBC 方法,因为它注定要失败。当涉及 Unicode 字符时,PHP 和 Access ODBC 不能很好地配合使用。

【讨论】:

【参考方案4】:

如果您要对值进行硬编码,那么准备是没有意义的。

另一方面,您正在承担风险,因为您可能会犯错误并且数据类型不匹配。

您似乎正在插入坐标,例如空白字符串 ('') 不会转换为浮点数。

尝试正确准备此查询:

$cmd = "INSERT INTO 
        temp_HEADER (`[LINE-ID]`, `PLANE`, `DISPLAY`, 
                     `X`, `Y`, `Z`, `LENGTH`, `SURF`, 
                     `ROCK`, `VARIA`, `LTYPE`, `NAME`) "
    . "VALUES(  ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$result = $db->prepare($cmd);
$success = $result->execute(array('101', '100', '', 
                                  100, 100, 100, 0, 0, 
                                  '', 1, 'LINE', 'TEMP'));    
if($success)
    echo "INSERT OK";
else
    echo "INSERT FAIL";

【讨论】:

以上是关于PDO 不能在 Access 数据库中插入新记录,但可以在同一个连接中读取和删除的主要内容,如果未能解决你的问题,请参考以下文章

如果记录已经存在或者在 PDO MySQL 插入查询中不存在,如何生成 javascript 警报?

pdo多次插入记录,等于数据库值

Pdo多次插入记录,等于数据库值

SQL 语句末尾的字符--Access 数据库

如果记录已存在,则为 PDO 数组

如何使用 PDO 从 php 文件中插入数据?