Laravel 查询生成器/如何阻止它添加方 [括号]?

Posted

技术标签:

【中文标题】Laravel 查询生成器/如何阻止它添加方 [括号]?【英文标题】:Laravel Query Builder / How to stop it from adding square [brackets]? 【发布时间】:2021-01-29 15:13:46 【问题描述】:

我试图让laravel 7xcloudera 提供的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'))->

但是,我无法获取 insertupdate 中的列名。

【问题讨论】:

【参考方案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 外观的语句方法:insertupdatedelete

// 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::insertDB::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 查询生成器/如何阻止它添加方 [括号]?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server表名为什么要加方括号?

如何使用 laravel 5 中的查询生成器从子查询中进行选择

如何在查询生成器 laravel 中执行此 SQL

我如何将 SQL 原始查询重写为 Laravel 查询生成器

如何检查表是不是已在 Laravel 查询生成器中加入

如何将此 sql 查询转换为 laravel 查询生成器