如何在Perl中使用占位符将变量注入Mysql

时间:2015-03-23 02:23:34

标签: perl

在我的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"进行此操作 如果可能的话。

3 个答案:

答案 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();