【问题标题】:Laravel Query Builder / How to stop it from adding square [brackets]?Laravel 查询生成器/如何阻止它添加方 [括号]?
【发布时间】: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 中的列名。

【问题讨论】:

    标签: laravel odbc laravel-7 impala laravel-query-builder


    【解决方案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 完全相同。
    猜你喜欢
    • 1970-01-01
    • 2014-05-06
    • 2014-02-21
    • 2012-04-10
    • 2017-09-09
    • 2013-12-09
    • 1970-01-01
    • 2019-01-28
    • 2015-06-04
    相关资源
    最近更新 更多