Eloquent 5.1 不支持绑定“语句”?
Binding on `statement` not supported in Eloquent 5.1?
我是 Laravel 的新手,正在尝试在 Eloquent 中进行字符串查询。我试图使用 DB::statement
,但我不断收到有关查询字符串中占位符的错误。似乎我的语法不正确,或者绑定未实现或不受支持?
我想使用 statement
的原因是因为我正在做一个 INSERT... SELECT
,我无法在 Eloquent 中找到任何相关文档。
这是我的代码:
$ php artisan tinker
Psy Shell v0.5.2 (PHP 5.6.13-0+deb8u1 — cli) by Justin Hileman
>>> echo \DB::statement('CREATE DATABASE :db', [':db'=>'test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 (SQL: CREATE DATABASE :db)'
>>> \DB::statement('CREATE DATABASE ?', ['test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 (SQL: CREATE DATABASE test)'
这是 PDO 的两种语法形式(?
和 :string
)。根据 documentation.
,DB
中的其他方法如 select
和 insert
支持此方法
这些错误的相关部分是 near '?' at line 1 (SQL: CREATE DATABASE :db)
和 near '?' at line 1 (SQL: CREATE DATABASE test)
。 MySQL 认为查询字符串中存在未绑定的 ?
。我什至没有在第一个查询中使用该语法。我的结论是 bind()
方法没有正确绑定我的占位符。
This question on Laracasts 询问语法,但没有可接受的答案。
编辑 一个答案说 statement()
不支持 CREATE
。我用 SELECT
尝试了一些查询,得到了相同的结果,两个占位符:
>>> \DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = a)'
>>> \DB::statement('SELECT 1 WHERE \'a\' = :letter', array(':letter'=>'a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = :letter)'
实际上,您可以在 DB::statement()
中使用 create
和 drop
查询,但是 named bindings 不以那种方式使用。
以下是一些会成功的查询。
drop
和 create
不接受绑定。
>>> \Db::statement('create database test')
=> true
>>> \Db::statement('drop database test')
=> true
不要在语句中使用反斜杠和单引号
>>> \Db::statement('insert into users (id, name) values (?, ?)', ['1', 'John'])
=> true
DB::statement()
只有 return ture
才成功,所以如果你想看到 select
结果,你应该使用 DB::select()
>>> \Db::statement('select * from users')
=> true
>>> \Db::select('select * from users')
=> [
{#770
+"id": 1,
+"name": "John",
},
]
删除第二个参数中的前导 :
。
>>> \Db::statement('update users set name = :name where id = :id', ['id' => 1, 'name' => 'John'])
=> true
如果您使用 DB::update
和 DB::delete
,您将获得影响行
>>> \Db::delete('delete from users where id = :id', ['id' => 1])
=> 1
您收到的错误仅与 Laravels DB::statement() 函数间接相关。他们都在
行的那个方法中失败了
return $me->getPdo()->prepare($query)->execute($bindings);
在文件 vendor/laravel/framework/src/Illuminate/Database/Connection.php
中
导致该失败的是对 PDO::prepare()
的调用
文件说:
Parameter markers can represent a complete data literal only. Neither part of literal, nor keyword, nor identifier, nor whatever arbitrary query part can be bound using parameters. For example, you cannot bind multiple values to a single parameter in the IN() clause of an SQL statement.
另请查看用户在上述 php.net 文档中提供的注释。另外看看 Can PHP PDO Statements accept the table or column name as parameter?
PDO 不支持您创建的示例。
您的 SELECT 示例失败的原因仅仅是因为语法无效。
\DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'))
您只是缺少 FROM 子句。这个例子在我的测试计算机上运行得很好:
$ret = \DB::statement('SELECT 1 FROM `users` WHERE `username` = ?', ["gregor"]);
但是
$ret = \DB::statement('SELECT 1 WHERE `username` = ?', ["testname"]);
生成您收到的确切错误。
另请注意,\DB::statement 不 return 任何资源。它只是通过 returning true 或 false 表示查询是否成功。
如果您想使用 INSERT...SELECT,您可以选择在 insert() 语句中使用 DB::raw()。一些谷歌搜索将帮助您找到合适的解决方案。也许作为起点:Raw Queries in Laravel, or How to use raw queries in Laravel
您要做的是通过绑定传递 table 名称。
DB::statement('select * from ?',['users'])
根据 this post,这是不可能的。
当然,如果你想清理数据,你可以使用一组短代码,如下所示:
$tables = ['users','test','another'];
查询看起来像这样:
$code = 0;
DB::statement("select * from $tables[$code] where a=?",[2]);
DB::statement("create table $tables[$code]");
我是 Laravel 的新手,正在尝试在 Eloquent 中进行字符串查询。我试图使用 DB::statement
,但我不断收到有关查询字符串中占位符的错误。似乎我的语法不正确,或者绑定未实现或不受支持?
我想使用 statement
的原因是因为我正在做一个 INSERT... SELECT
,我无法在 Eloquent 中找到任何相关文档。
这是我的代码:
$ php artisan tinker
Psy Shell v0.5.2 (PHP 5.6.13-0+deb8u1 — cli) by Justin Hileman
>>> echo \DB::statement('CREATE DATABASE :db', [':db'=>'test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 (SQL: CREATE DATABASE :db)'
>>> \DB::statement('CREATE DATABASE ?', ['test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 (SQL: CREATE DATABASE test)'
这是 PDO 的两种语法形式(?
和 :string
)。根据 documentation.
DB
中的其他方法如 select
和 insert
支持此方法
这些错误的相关部分是 near '?' at line 1 (SQL: CREATE DATABASE :db)
和 near '?' at line 1 (SQL: CREATE DATABASE test)
。 MySQL 认为查询字符串中存在未绑定的 ?
。我什至没有在第一个查询中使用该语法。我的结论是 bind()
方法没有正确绑定我的占位符。
This question on Laracasts 询问语法,但没有可接受的答案。
编辑 一个答案说 statement()
不支持 CREATE
。我用 SELECT
尝试了一些查询,得到了相同的结果,两个占位符:
>>> \DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = a)'
>>> \DB::statement('SELECT 1 WHERE \'a\' = :letter', array(':letter'=>'a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = :letter)'
实际上,您可以在 DB::statement()
中使用 create
和 drop
查询,但是 named bindings 不以那种方式使用。
以下是一些会成功的查询。
drop
和 create
不接受绑定。
>>> \Db::statement('create database test')
=> true
>>> \Db::statement('drop database test')
=> true
不要在语句中使用反斜杠和单引号
>>> \Db::statement('insert into users (id, name) values (?, ?)', ['1', 'John'])
=> true
DB::statement()
只有 return ture
才成功,所以如果你想看到 select
结果,你应该使用 DB::select()
>>> \Db::statement('select * from users')
=> true
>>> \Db::select('select * from users')
=> [
{#770
+"id": 1,
+"name": "John",
},
]
删除第二个参数中的前导 :
。
>>> \Db::statement('update users set name = :name where id = :id', ['id' => 1, 'name' => 'John'])
=> true
如果您使用 DB::update
和 DB::delete
>>> \Db::delete('delete from users where id = :id', ['id' => 1])
=> 1
您收到的错误仅与 Laravels DB::statement() 函数间接相关。他们都在
行的那个方法中失败了return $me->getPdo()->prepare($query)->execute($bindings);
在文件 vendor/laravel/framework/src/Illuminate/Database/Connection.php
中导致该失败的是对 PDO::prepare()
的调用文件说:
Parameter markers can represent a complete data literal only. Neither part of literal, nor keyword, nor identifier, nor whatever arbitrary query part can be bound using parameters. For example, you cannot bind multiple values to a single parameter in the IN() clause of an SQL statement.
另请查看用户在上述 php.net 文档中提供的注释。另外看看 Can PHP PDO Statements accept the table or column name as parameter?
PDO 不支持您创建的示例。
您的 SELECT 示例失败的原因仅仅是因为语法无效。
\DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'))
您只是缺少 FROM 子句。这个例子在我的测试计算机上运行得很好:
$ret = \DB::statement('SELECT 1 FROM `users` WHERE `username` = ?', ["gregor"]);
但是
$ret = \DB::statement('SELECT 1 WHERE `username` = ?', ["testname"]);
生成您收到的确切错误。
另请注意,\DB::statement 不 return 任何资源。它只是通过 returning true 或 false 表示查询是否成功。
如果您想使用 INSERT...SELECT,您可以选择在 insert() 语句中使用 DB::raw()。一些谷歌搜索将帮助您找到合适的解决方案。也许作为起点:Raw Queries in Laravel, or How to use raw queries in Laravel
您要做的是通过绑定传递 table 名称。
DB::statement('select * from ?',['users'])
根据 this post,这是不可能的。
当然,如果你想清理数据,你可以使用一组短代码,如下所示:
$tables = ['users','test','another'];
查询看起来像这样:
$code = 0;
DB::statement("select * from $tables[$code] where a=?",[2]);
DB::statement("create table $tables[$code]");