Laravel 查询生成器/如何阻止它添加方 [括号]?
Posted
技术标签:
【中文标题】Laravel 查询生成器/如何阻止它添加方 [括号]?【英文标题】:Laravel Query Builder / How to stop it from adding square [brackets]? 【发布时间】:2021-01-29 15:13:46 【问题描述】:我试图让laravel 7x
与cloudera
提供的impala/kudu
一起工作。我得到了ODBC connection
,它连接良好,如果您运行原始 sql 查询,它也可以正常工作。
数据库连接入口:
'impala_connect' => [
'driver' => 'sqlsrv',
'odbc' => true,
'odbc_datasource_name'=> 'cloudera_odbc_connection',
'host' => '',
'port' => '',
'database' => '',
'username' => '',
'password' => '',
'pooling' => false,
],
原始查询工作正常:
DB::connection('impala_connect')->raw("insert into test1 values(4, 'z')");
DB::connection('impala_connect')->select(DB::raw('select * from test1'));
查询生成器失败:
但是,当我使用 laravel 的查询构建器运行一些查询时,它们都失败了,并带有 laravel 自己添加的括号。
DB::connection('impala_connect')->table('test1')->get(['id', 'val']);
//or
DB::connection('impala_connect')->table('test1')->insert([
'id'=> 5,
'val'=> 'z'
]);
这是我得到的错误:
SQLSTATE: General error: 0 [Cloudera][ImpalaODBC] (110) Error while executing a query in Impala : ParseException: Syntax error in line 1: select [id], [val] from [test1] ^
Encountered: COMMA Expected: CASE, CAST, DEFAULT, EXISTS, FALSE, IF, INTERVAL, LEFT, NOT, NULL, REPLACE, RIGHT, TRUNCATE, TRUE, IDENTIFIER
CAUSED BY: Exception: Syntax error (SQLPrepare[0] at pdo_odbc\odbc_driver.c:206) (SQL: select [id], [val] from [test1])
您可以看到实际查询变成了每个项目的括号,这就是它失败的地方。
那么你如何让 laravel 不包裹括号?!
编辑:
我确实想出了如何获得至少不带括号的表名。
->table(db::raw('test1'))->
但是,我无法获取 insert
和 update
中的列名。
【问题讨论】:
【参考方案1】:尝试使用select
,然后使用get
:
DB::connection('impala_connect')->table('test1')->select('id', 'val')->get();
【讨论】:
@RaheelHasan 你能把当前代码贴在某个地方吗?【参考方案2】:您正在使用 SQL Server 驱动程序。 'driver' => 'sqlsrv'
我对 impala 一无所知,但它首先与 SQL Server 的语法兼容吗?
括在方括号 ([id]
) 中的列通常是关键字或包含特殊字符或空格。 Laravel 在使用 sqlsrv
驱动程序时默认将所有内容都包含在括号中。这是常见的行为。
在使用 mysql
驱动程序时,它通过将所有内容包装在反引号 ``
中来做同样的事情。
这是使用查询生成器使用不同的驱动程序创建简单的 SQL 查询SELECT id, name FROM table
的结果。正如您所看到的,它对待每个选定的列和表名,就好像它们在每个驱动程序中都有特殊字符一样。这样做是为了保持一致性。
>>> DB::connection('mysql')->table('table')->select('id', 'name')->toSql()
=> "select `id`, `name` from `table`"
>>> DB::connection('pgsql')->table('table')->select('id', 'name')->toSql()
=> "select "id", "name" from "table""
>>> DB::connection('sqlite')->table('table')->select('id', 'name')->toSql()
=> "select "id", "name" from "table""
>>> DB::connection('sqlsrv')->table('table')->select('id', 'name')->toSql()
=> "select [id], [name] from [table]"
我得出结论,sqlsrv
驱动程序与 Impala 的语法不兼容。包装由位于vendor\laravel\framework\src\Illuminate\Database\Query\Grammars\SqlServerGrammar.php
中的函数wrapValue
完成。
完全不推荐,但如果你别无选择,你可以编辑它。
如果您不介意原始查询,另一种选择是简单地使用 DB
外观的语句方法:insert
、update
、delete
。
// returns bool
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
// returns int (number of rows affected)
DB::update('update users set name = ? where id = ?', ['Dayle', 1]);
DB::delete('delete from users where name = ?', ['Dayle']);
【讨论】:
laravel 中的 sqlsrv 通过odbc_datasource_name
连接设置提供到 odbc 的连接。这仅在 sqlsrv 驱动程序中可用,在任何其他驱动程序中均不可用。
我试图查看wrapValue
,但是我不想手动更新供应商代码,因为那样当我升级框架时这将是一个大问题
使用->table(db::raw('test1'))->
我至少得到了不带括号的表名。但无法弄清楚更新和插入调用中的列。
我认为sqlsrv驱动提供的odbc对SQL Server本身来说是非常特殊的。
如果运行原始 sql 查询没有问题,您可以尝试DB::insert
和DB::update
。它们的语法如下DB::insert(sql-query, placeholders)
。你用 ?作为占位符来清理输入。例如:DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
DB::update
具有相同的语法。它们之间的区别:DB::insert
返回布尔值,DB::update
返回 int(更新的行数)。还有DB::delete
的行为与DB::update
完全相同。以上是关于Laravel 查询生成器/如何阻止它添加方 [括号]?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 laravel 5 中的查询生成器从子查询中进行选择