简体   繁体   English

在简单的mysql查询中使用哈希值(perl)

[英]Using a hash value in a simple mysql query (perl)

Can someone help me figure out the correct syntax of 有人可以帮我弄清楚正确的语法

for (my $i = 0; $i <=3; $i++)
{

    $store = qq(INSERT INTO main (creator_name,relationship) 
    VALUES("$data{creatorname}",$data{"relationship$i"}) );

The problem lies with $data{"relationship$1"}. 问题出在$ data {“relationship $ 1”}上。 I'm looping because I have 'relationship1', 'relationship2', and 'relationship3' in my data hash. 我正在循环,因为我的数据哈希中有'relationship1','relationship2'和'relationship3'。 I didn't want to go through 3 separate mysql queries to get the job done so I'm trying to loop over it. 我不想通过3个单独的mysql查询来完成工作,所以我试图循环它。

Any pointers? 有什么指针吗?

EDIT: 编辑:

Thanks for your help with pointing me towards placeholders. 感谢您帮助我指向占位符。 It's not working as placeholders and it looks like it's because of 它不是占位符,它看起来像是因为

  $sth->execute($data{creatorname},$data{relationship},"DATE_ADD(NOW(), INTERVAL $interval)"

I have a DATE_ADD now that I'm using, it doesn't look like it likes to be used as a placeholder. 我现在有一个DATE_ADD,它看起来不像是用作占位符。

As @mob says, you should use query parameters instead of fighting with how to interpolate variables directly into strings. 正如@mob所说,你应该使用查询参数而不是如何将变量直接插入字符串。

$store = qq(INSERT INTO main (creator_name, relationship) VALUES (?, ?));
$st = $dbi->prepare($store);
for (my $i = 0; $i < 3; $i++)
{
  $st->execute($data{creatorname}, $data{"relationship$i"});
}

Advantages of using parameters: 使用参数的优点:

  • Easier to code, without worrying about awkward string interpolation. 更容易编码,而不用担心尴尬的字符串插值。
  • Slightly better for performance, because the SQL statement is parsed once, instead of repeatedly during each loop iteration. 性能稍微好一些,因为SQL语句被解析一次,而不是在每次循环迭代期间重复。
  • Safer with respect to application security; 在应用程序安全性方面更安全; good defense against SQL injection . 防止SQL注入的良好防御。

Re your comment: 你的评论:

An SQL parameter can be used only in place of a single scalar value . SQL参数只能用于代替单个标量值 Not an expression, or a table name or column name, or a list of values, or SQL keywords. 不是表达式,表名称或列名称,值列表或SQL关键字。 Basically, any value you pass for the parameter value will be treated as though you had put quotes around it (there are some nuances to that, but it gives you the approximate idea). 基本上,您为参数值传递的任何值都将被视为您已在其周围加上引号(这有一些细微差别,但它为您提供了近似的想法)。

Given the expression you described, I'd write the code like this: 鉴于您描述的表达式,我会编写如下代码:

$store = qq(INSERT INTO main (creator_name, relationship, complicated_column) 
    VALUES (?, ?, DATE_ADD(NOW(), INTERVAL ? HOUR)));
$st = $dbi->prepare($store);
for (my $i = 0; $i < 3; $i++)
{
  $st->execute($data{creatorname}, $data{"relationship$i"}, $interval);
}

Re answer from @harmic: 从@harmic 回答

This is awkward to reply to another answer by adding to my own answer, but I wanted to share a code test that demonstrates the "double-interpolation" does in fact work. 通过添加到我自己的答案回复另一个答案是很尴尬的,但是我想分享一个代码测试,它演示了“双插值”确实有效。

$ cat test.pl
$i = 1;
$data{"key$i"} = "word";
$s = qq(string with parentheses ($data{"key$i"}));
print $s, "\n";

$ perl test.pl
string with parentheses (word)

The output of running this Perl script shows that the interpolation worked. 运行此Perl脚本的输出显示插值有效。

As pointed out by mob and Bill, if possible it is best to use place holders, but that's not the reason your code is not working. 正如暴徒和比尔所指出的,如果可能的话,最好使用占位符,但这并不是你的代码不起作用的原因。

It is not working because you are trying to do two levels of variable interpolation in one string: first interpolate $i into "relationship$i", then interpolate $data{"relationship$i"} into the larger string quoted with qq. 它不起作用,因为你试图在一个字符串中进行两级变量插值:首先将$ i插入“relationship $ i”,然后将$ data {“relationship $ i”}插入到qq引用的较大字符串中。 They will not nest like that. 他们不会那样筑巢。

This would work: 这可行:

for (my $i = 0; $i <=3; $i++)
{
    my $relationship = $data{"relationship$i"}
    $store = qq(INSERT INTO main (creator_name,relationship) 
    VALUES("$data{creatorname}",$relationship ) );

It's a bit hard on the eyes, but if you always have three rows to enter you could do it all in one execute() : 这对眼睛来说有点难,但是如果你总是要输入三行,你可以在一个execute()完成所有操作:

my $sth = $dbh->prepare(<<'__eosql');
          INSERT INTO main (time_column, creator_name, relationship)
          SELECT NOW() + INTERVAL ? HOUR, -- placeholder for $interval
                 ?,                       -- $data{creatorname}
                 relation
            FROM (SELECT ? AS relation    -- $data{relationship1}
                   UNION ALL
                  SELECT ?                -- $data{relationship2}
                   UNION ALL
                  SELECT ?) d             -- $data{relationship3}
          __eosql

$sth->execute($interval, @data{qw(creatorname relationship1 relationship2 relationship3)});

That uses a hash slice to pull the values out of %data . 这使用哈希切片%data提取值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM