为了账号安全,请及时绑定邮箱和手机立即绑定

尝试插入 SQL Server 数据库时出现“PK”错误附近的语法错误

尝试插入 SQL Server 数据库时出现“PK”错误附近的语法错误

PHP
长风秋雁 2023-09-08 21:36:46
数据库异常 – yii\db\ExceptionError Info: Array(    [0] => HY000    [1] => 102    [2] => Incorrect syntax near 'PK'. [102] (severity 15) [INSERT INTO [ORDERS] ([ID], [STATUS], [ZIPFILE], [COLOR], [PRICE]) VALUES (87, 1,'PK]    [3] => -1    [4] => 15)↵ 导致:PDOException SQLSTATE[HY000]:一般错误:102 'PK' 附近的语法不正确。[102](严重性 15)[插入 [订单]([ID]、[状态]、[ZIPFILE]、[颜色]、[价格])值 (87, 1,'PK]在 yii2 应用程序中,我尝试使用 file_get_uploads php 函数上传 zip 文件,首先将 zip 转换为二进制并将其保存到 SQL Server 数据库中的“ZIPFILE”列中,但收到上述错误。看起来 PK 后面的特殊字符会截断 ZIPFILE 的值以及 SQL 插入字符串中紧随其后的任何内容。如果我使用 PHP 函数转义特殊字符addslashes(),我能够完成插入,但 zip 文件会因为额外的斜杠而被损坏。更改编码不是一个选项,因为我使用另一个应用程序从数据库下载数据,并且该应用程序要求值采用此编码。有没有办法在不损坏 zip 文件的情况下转义特殊字符?我添加了一些代码以使事情更加清晰。应用程序使用Yii2框架控制器代码public function actionCreate(){    $model = new Orders();    $model->load(Yii::$app->request->post())       //populates ZIPFILE property with binary value of the ASCII encoded ZIPFILE string(pre-populated) compressed to a .zip file and read using file_get_contents in the Zip model    $model->ZIPFILE = (new Zip)->asBinaryString($model->ZIPFILE);        if ($model->save()) {        return $this->redirect(['view', 'id' => $model->ID]);    } else {        return $this->render(            'create', [                'model' => $model,            ]);    }}在 Zip 模型中private string $_tempFolder = '/somecache/';public function asBinaryString($content): ?string    {        $fileName = $this->create($content);            $fileAsBinary = file_get_contents(Yii::$app->basePath . $this->_tempFolder . $fileName);                return $fileAsBinary;       }加载回 $model->ZIPFILE 的字符串看起来像这样“PKa��PM?ٟ�1590409143.RTFu��n�0�_e`���Os�R��j��*�Ƅ�A” �5Dq��@0……”无法使用数据库中的链接将文件存储到磁盘上,因为这是对旧应用程序的增强,需要将数据作为 zip 存储在数据库中。尝试通过使用 PHP bin2hex() 将二进制 zip 转换为十六进制来更接近解决方案,但没有成功。十六进制没有特殊字符;因此,$model 保存得很好,只是保存到 SQL Server 的 zip 文件无法被其他应用程序读取。这不是一个简单的拼写错误问题,并且已尝试在此处使用准备好的语句,但不起作用。
查看完整描述

1 回答

?
拉莫斯之舞

TA贡献1820条经验 获得超10个赞

我花了至少10天的时间在网上广泛搜索并测试了各种解决方案才解决这个问题。


上述问题的答案是不可能将二进制字符串直接保存到 SQL Server 数据库中。该文件需要作为字符串发送hex。


解决方案:


public function asBinary($content): ?string

{

    $fileName = $this->create($content);

    $fileAsBinary = file_get_contents(Yii::$app->cache->cachePath . '/' . $fileName);

    return $fileAsBinary;   

}


/**

* zips file in cache folder into archive

*/

public function create($content): ?string

{

    $zipName = \microtime();

    try {

            $zip = new \ZipArchive;

            if ($zip->open(Yii::$app->cache->cachePath . '/'  . $zipName, \ZipArchive::CREATE) === true) {

                $zip->addFromString(time().'.RTF', $content);

                $zip->close();

            } else {

                throw new Exception(Yii::t('app', 'Archive could not be created in cache folder.'));

            }

    } catch (\Throwable $th) {

        throw $th;

    } 

    return $zipName ?? null;      

}


//return file as Hex string

public function asHex($content): string

{

    $fileAsBinary = $this->asBinary($content);

    $unpackedBinaryFile = unpack('H*hex', $fileAsBinary);

    $fileAsHex = '0x' . $unpackedBinaryFile['hex'];        

    return $fileAsHex;   

}

填充 $model 中的 ZIPFILE


$model->ZIPFILE = (new Zip)->asHex($model->ZIPFILE);

zip 文件需要转换为hex可以直接保存到 SQL Server 中的字符串。VARBINARYSQL Server在插入数据库时会将其转换为。


由于不清楚的原因,我无法使用 Yii2 的准备好的语句传递 ZIPFILE。每次都会出错。另外,无法使用 ActiveRecord 的$model->save()方法进行保存。必须使用 SQL 查询字符串插入。如果有人能说出原因,那就太好了。


查看完整回答
反对 回复 2023-09-08
  • 1 回答
  • 0 关注
  • 53 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信