tp6连接oracle数据库save和insert语句执行成功但是报ORA-00936: 缺失表达式错误

在使用ThinkPHP6连接Oracle数据库时,遇到使用save方法导致更新操作,以及insert方法成功但报ORA-00936错误的问题。原因是TP6基于MySQL设计,需主键,而Oracle无此要求。解决方法是在PDOConnection.php中注释获取主键的判断,使$lastInsId强制为0。但此法无法解决save方法始终转向update的问题,建议使用update和insert原生方法。

SQLSTATE[HY000]: General error: 936 OCIStmtExecute: ORA-00936: 缺失表达式 (ext\pdo_oci\oci_statement.c:157)

/**
     * 获取最近插入的ID
     * @access public
     * @param BaseQuery $query    查询对象
     * @param string    $sequence 自增序列名
     * @return mixed
     */
    public function getLastInsID(BaseQuery $query, string $sequence = null)
    {
        $pdo    = $this->linkID->query("select {$sequence}.currval as id from dual");
        $result = $pdo->fetchColumn();

        return $result;
    }

    protected function supportSavepoint(): bool
    {
        return true;
    }

错误现象:
使用thinkphp6连接oracle数据库时
使用save方法永远跳转到update
使用insert方法执行语句成功,但是总是报ORA-00936错误

原因分析:
tp6主要是基于mysql
进行设计,mysql强制要求每个表都有主键,然而,oracle对此没有硬性要求。
所以tp6在insert或者update访问数据表时候都会先取得主键,然后再进行访问。
由于oracle大部分表格都没有主键,所以抛出错误。

解决方法:
临时方法:禁止tp6在insert和update时获得主键。
具体操作:
\vendor\topthink\think-orm\src\db\PDOConnection.php
944行~945行,注释掉判断函数,然后让$lastInsId强制为0

$sequence  = $options['sequence'] ?? null;
            //$lastInsId = $this->getLastInsID($query, $sequence);
            $lastInsId = 0;

controller当中使用函数:
(xxxxx是表名)

Db::table('xxxxx')->update($data);

Db::table('xxxxx')->insert($data);

xxxxx::update($data);

xxxxx::insert($data);

注意,这个方法不能解决save总是跳转到update的方法,所以老老实实用update和insert吧。

ORA-00936Oracle 数据库中常见的语法错误,表示 **“缺失表达式”**(missing expression),通常是因为 SQL 语句中某个地方缺少了必要的表达式或关键字,导致 Oracle 无法解析语句--- ### 🔍 常见原因及解决方法: #### ✅ 1. **列别名使用了关键字或未正确使用引号** ```sql -- 错误示例 SELECT name as order FROM employees; -- 正确示例 SELECT name AS "order" FROM employees; ``` #### ✅ 2. **WHERE 条件中表达式不完整** ```sql -- 错误示例 SELECT * FROM employees WHERE ; -- 正确示例 SELECT * FROM employees WHERE department_id = 10; ``` #### ✅ 3. **INSERT 语句字段或值不匹配** ```sql -- 错误示例 INSERT INTO employees(name, salary) VALUES ('Tom'); -- 正确示例 INSERT INTO employees(name, salary) VALUES ('Tom', 5000); ``` #### ✅ 4. **SELECT 中使用了无效的表达式或缺少字段** ```sql -- 错误示例 SELECT FROM employees; -- 正确示例 SELECT name, salary FROM employees; ``` #### ✅ 5. **使用了错误的函数或表达式格式** ```sql -- 错误示例 SELECT NVL() FROM dual; -- 正确示例 SELECT NVL(name, '无名氏') FROM employees; ``` --- ### 🛠 排查建议: 1. **定位错误位置**: - 根据提示的 `line: 96 pos: 33`,打开你的 SQL 文件,定位到第 96 行,从第 33 个字符附近开始检查。 2. **逐段检查 SQL 语法**: - 查看是否有空的 `SELECT`, `WHERE`, `INSERT INTO ... VALUES()` 等结构。 - 查看是否有关键字作为列名但未加双引号。 - 检查函数是否正确使用,参数是否完整。 --- ### ✅ 示例修复: #### 原始错误 SQL(假设): ```sql SELECT employee_id, , name FROM employees; ``` #### 修复后: ```sql SELECT employee_id, name FROM employees; ``` --- ### ✅ 示例 2:使用关键字作为列别名 #### 原始错误 SQL: ```sql SELECT name as group FROM users; ``` #### 修复后: ```sql SELECT name AS "group" FROM users; ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值