在我的perl脚本中尝试使用占位符进行Mysql例程时,我一直遇到错误。
代码:
use DBI;
my $driver = "mysql";
my $database = "database";
my $user = "exxxxxx";
my $password = "xxxxx";
my $dsn = "DBI:mysql:$database;mysql_local_infile=ON";
my $dbh = DBI->connect($dsn,$user,$password);
$dbh->do("SET \@tempc5 = (SELECT temp FROM day5 WHERE time = '00:00') ");
my $inter1 = i24;
$sth = $dbh->prepare( "SET \@sumadd5 = (SELECT ? FROM humid WHERE temp=\@tempc5) " );
$sth->bind_param( 1, $inter1 );
$sth->finish();
$dbh->disconnect();
这会产生以下错误:
Global symbol "$sth" requires explicit...
如果我添加my $sth
,我会收到以下错误:
Scalar found where operator expected...
请注意,我不反对使用$dbh->do("SET"
进行此操作
如果可能的话。
答案 0 :(得分:1)
根据mysql_stmt_prepare()
的MySQL手册,不允许使用占位符作为prepare
背后的函数。
标记仅在SQL语句的某些位置是合法的。对于 例如,它们被允许在INSERT的VALUES()列表中 语句(指定行的列值)或比较 使用WHERE子句中的列来指定比较值。 但是,它们不允许用于标识符(例如表格或表格) 列名),或指定二元运算符的两个操作数 作为=等号。后一种限制是必要的,因为它 将无法确定参数类型。一般来说, 参数仅在数据操作语言(DML)中是合法的 语句,而不是数据定义语言(DDL)语句。
如果您考虑一下,准备一个可以更改列的语句是没有意义的。语句的准备包括执行计划,但是你不能计划执行一个你不知道给定列是否有索引的语句。
答案 1 :(得分:1)
您不能在那里使用占位符。
当您致电prepare
时,有关表格的所有结构信息都会被添加到查询中,等待您在execute
查询时传递数据值以替换占位符。
但是你试图使用占位符来表示列名,这是表结构的一部分。
如果您将Perl语法修复为:
my $inter1 = 'i24';
my $sth = $dbh->prepare( "SET \@sumadd5 = (SELECT ? FROM humid WHERE temp=\@tempc5) " );
$sth->execute($inter1);
它应该运行,但?
将被视为数据值而不是列名(结构信息)。因此,您将获得SQL查询的结果
SET @sumadd5 = (SELECT 'i24' FROM humid WHERE temp=@tempc5)
而不是
SET @sumadd5 = (SELECT i24 FROM humid WHERE temp=@tempc5)
子查询将为每个匹配的行返回文字值“i24”,而不是列i24
中的值。
答案 2 :(得分:-2)
您没有引用$inter1
的值。将$inter1 = i24;
更改为$inter1 = 'i24';
。刚刚在您的代码中编辑,这不会给您语法错误。
use warnings;
use strict;
use DBI;
my $driver = "mysql";
my $database = "database";
my $user = "exxxxxx";
my $password = "xxxxx";
my $dsn = "DBI:mysql:$database;mysql_local_infile=ON";
my $dbh = DBI->connect($dsn,$user,$password);
$dbh->do("SET \@tempc5 = (SELECT temp FROM day5 WHERE time = '00:00') ");
my $inter1 = 'i24';
my $sth = $dbh->prepare( "SET \@sumadd5 = (SELECT ? FROM humid WHERE temp=\@tempc5) " );
$sth->bind_param( 1, $inter1 );
$sth->finish();
$dbh->disconnect();