我是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
)。根据{{3}},DB
中的其他方法(例如select
和insert
)支持此功能。
这些错误的相关部分是near '?' at line 1 (SQL: CREATE DATABASE :db)
和near '?' at line 1 (SQL: CREATE DATABASE test)
。 MySQL认为查询字符串中有一个未绑定的?
。我甚至没有在第一个查询中使用该语法。我的结论是bind()
方法没有正确绑定我的占位符。
documentation询问语法,但没有接受答案。
修改一个答案说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)'
答案 0 :(得分:1)
实际上,您可以在create
中使用drop
和DB::statement()
查询,但不会以这种方式使用命名绑定。
以下是一些会成功的查询。
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()
仅在成功时返回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
答案 1 :(得分:1)
您收到的错误只与Laravels DB :: statement()函数间接相关。它们都在该方法中失败
return $me->getPdo()->prepare($query)->execute($bindings);
在文件vendor / laravel / framework / src / Illuminate / Database / Connection.php中
对失败负责的是对PDO::prepare()
的调用Docuemenation说:
参数标记只能表示完整的数据文字。文字,关键字,标识符和任意查询部分都不能使用参数绑定。例如,您不能将多个值绑定到SQL语句的IN()子句中的单个参数。
另请参阅上面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不会返回任何资源。它只是通过返回true或false来表示查询已成功。
如果要使用INSERT ... SELECT,则可以在insert()语句中使用DB :: raw()。一些谷歌搜索将帮助您,找到适当的解决方案。可能作为起点:Raw Queries in Laravel或How to use raw queries in Laravel
答案 2 :(得分:1)
您要做的是通过绑定传递表名。
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]");