Mysql Perl dbi中的绑定参数导致外键约束失败
我有这样一个想法,我想做一个sub,它可以接受一个select查询,然后将结果复制到同一个表中,但要做一些重要的更改。我的问题是,我运行sub的某些表具有包含许多不同字符的大型文本字段,其中一些字段将破坏我的insert语句。然后,我将insert更改为使用参数绑定,但在执行此操作时,由于“profile”字段上存在外键约束,我的查询将无法运行:Mysql Perl dbi中的绑定参数导致外键约束失败,mysql,perl,dbi,parameterbinding,Mysql,Perl,Dbi,Parameterbinding,我有这样一个想法,我想做一个sub,它可以接受一个select查询,然后将结果复制到同一个表中,但要做一些重要的更改。我的问题是,我运行sub的某些表具有包含许多不同字符的大型文本字段,其中一些字段将破坏我的insert语句。然后,我将insert更改为使用参数绑定,但在执行此操作时,由于“profile”字段上存在外键约束,我的查询将无法运行: DBD::mysql::st execute failed:无法添加或更新子行:外键约束失败(retrieverresult,约束result\u
DBD::mysql::st execute failed:无法添加或更新子行:外键约束失败(retriever
result
,约束result\u ibfk\u 2
外键(profile
)在/create\query.pl第62行的DELETE CASCADE上引用profile
(id
)。
无法添加或更新子行:外键约束失败(retriever
result
,约束result\u ibfk\u 2
外键(profile
)引用profile
(id
)删除级联更新级联)
有关该表的一些信息:
CREATE TABLE `result` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`profile` mediumint(8) unsigned NOT NULL DEFAULT '0',
CONSTRAINT `result_ibfk_2` FOREIGN KEY (`profile`) REFERENCES `profile` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
) ENGINE=InnoDB AUTO_INCREMENT=1037028383 DEFAULT CHARSET=utf8
这是我的密码:
#Define which rows to change
my $rows_to_change = {
'profile' => 621420,
};
#Define a select query, the results will then be copyed over
my $sql = "select * from result where profile = 639253";
#Define which table to work with
my $table = "result";
my @inserted_ids = create_insert_query($sql, $table, $rows_to_change);
for my $id (@inserted_ids){
print $id."\n";
}
$dbh->rollback();
$dbh->disconnect();
sub create_insert_query{
my $select = shift;
my $table = shift;
my $rows_to_change = shift;
my $result = $dbh->prepare($select);
$result->execute() or die $dbh->errstr;
my @inserted_ids;
while(my $row = $result->fetchrow_hashref){
delete $row->{'id'};
foreach my $key (keys %{$rows_to_change}){
$row->{$key} = $rows_to_change->{$key};
}
my @fields;
my @values;
for my $key (keys %{$row}){
push(@fields, $key);
if(defined $row->{$key}){
push(@values, "'$row->{$key}'");
}else{
push(@values, "null");
}
}
my $fields_string = join(", ", @fields);
my $values_string = join(", ", @values);
my $questionmarks = join( ',', map { '?' } @values );
my $query = qq[insert into $table ($fields_string) values ($questionmarks)];
my $sth = $dbh->prepare($query);
$sth->execute(@values) or die $dbh->errstr;
push(@inserted_ids, $sth->{mysql_insertid});
}
return @inserted_ids;
}
怎么办
你想要的是:
$fieldnames = join ', ' => map { $dbh->quote_identifier($_) } keys %row;
$placeholders = join ', ' => map { '?' } values %row;
...
$sth = $dbh->prepare('INSERT INTO t ($fieldnames) VALUES ($placeholders)');
$sth->execute(values %row);
(此呼叫是为了安全起见,以防您的列名与关键字冲突或需要特殊编码或引用。)
为什么?
您当前的问题是,您正在引用值,然后绑定到占位符(将值与引号绑定),并且将字符串“null”绑定到占位符(将字符串“null”绑定)。由于FKEY可能不是文字字符串“null”,也不是表示带引号的数字的字符串(例如,它可能是数字123,而不是带有嵌入引号的字符串“'123”),因此无法满足某些外键约束
作为参考,绑定字符串、包含引号的字符串、数字文本和DBI下的undef
通常是这样工作的:
my $sth = $dbh->prepare('INSERT INTO t (a,b,c,d,e) VALUES (?,?,?,?,?)');
$sth->execute("'quoted'", 'null', undef, 123, "a string");
# Approximately the same as:
# INSERT INTO t (a,b,c,d,e) VALUES ('''quoted''', 'null', NULL, 123, 'a string');
# ^ ^ ^ ^ ^
# a string with quotes ----+ | | | |
# | | | |
# a string (not the NULL value) -------+ | | |
# | | |
# NULL (not the string 'null')----------------+ | |
# | |
# numeric literal ----------------------------------+ |
# |
# another string -----------------------------------------+
怎么办
你想要的是:
$fieldnames = join ', ' => map { $dbh->quote_identifier($_) } keys %row;
$placeholders = join ', ' => map { '?' } values %row;
...
$sth = $dbh->prepare('INSERT INTO t ($fieldnames) VALUES ($placeholders)');
$sth->execute(values %row);
(此呼叫是为了安全起见,以防您的列名与关键字冲突或需要特殊编码或引用。)
为什么?
您当前的问题是,您正在引用值,然后绑定到占位符(将值与引号绑定),并且将字符串“null”绑定到占位符(将字符串“null”绑定)。由于FKEY可能不是文字字符串“null”,也不是表示带引号的数字的字符串(例如,它可能是数字123,而不是带有嵌入引号的字符串“'123”),因此无法满足某些外键约束
作为参考,绑定字符串、包含引号的字符串、数字文本和DBI下的undef
通常是这样工作的:
my $sth = $dbh->prepare('INSERT INTO t (a,b,c,d,e) VALUES (?,?,?,?,?)');
$sth->execute("'quoted'", 'null', undef, 123, "a string");
# Approximately the same as:
# INSERT INTO t (a,b,c,d,e) VALUES ('''quoted''', 'null', NULL, 123, 'a string');
# ^ ^ ^ ^ ^
# a string with quotes ----+ | | | |
# | | | |
# a string (not the NULL value) -------+ | | |
# | | |
# NULL (not the string 'null')----------------+ | |
# | |
# numeric literal ----------------------------------+ |
# |
# another string -----------------------------------------+
怎么办
你想要的是:
$fieldnames = join ', ' => map { $dbh->quote_identifier($_) } keys %row;
$placeholders = join ', ' => map { '?' } values %row;
...
$sth = $dbh->prepare('INSERT INTO t ($fieldnames) VALUES ($placeholders)');
$sth->execute(values %row);
(此呼叫是为了安全起见,以防您的列名与关键字冲突或需要特殊编码或引用。)
为什么?
您当前的问题是,您正在引用值,然后绑定到占位符(将值与引号绑定),并且将字符串“null”绑定到占位符(将字符串“null”绑定)。由于FKEY可能不是文字字符串“null”,也不是表示带引号的数字的字符串(例如,它可能是数字123,而不是带有嵌入引号的字符串“'123”),因此无法满足某些外键约束
作为参考,绑定字符串、包含引号的字符串、数字文本和DBI下的undef
通常是这样工作的:
my $sth = $dbh->prepare('INSERT INTO t (a,b,c,d,e) VALUES (?,?,?,?,?)');
$sth->execute("'quoted'", 'null', undef, 123, "a string");
# Approximately the same as:
# INSERT INTO t (a,b,c,d,e) VALUES ('''quoted''', 'null', NULL, 123, 'a string');
# ^ ^ ^ ^ ^
# a string with quotes ----+ | | | |
# | | | |
# a string (not the NULL value) -------+ | | |
# | | |
# NULL (not the string 'null')----------------+ | |
# | |
# numeric literal ----------------------------------+ |
# |
# another string -----------------------------------------+
怎么办
你想要的是:
$fieldnames = join ', ' => map { $dbh->quote_identifier($_) } keys %row;
$placeholders = join ', ' => map { '?' } values %row;
...
$sth = $dbh->prepare('INSERT INTO t ($fieldnames) VALUES ($placeholders)');
$sth->execute(values %row);
(此呼叫是为了安全起见,以防您的列名与关键字冲突或需要特殊编码或引用。)
为什么?
您当前的问题是,您正在引用值,然后绑定到占位符(将值与引号绑定),并且将字符串“null”绑定到占位符(将字符串“null”绑定)。由于FKEY可能不是文字字符串“null”,也不是表示带引号的数字的字符串(例如,它可能是数字123,而不是带有嵌入引号的字符串“'123”),因此无法满足某些外键约束
作为参考,绑定字符串、包含引号的字符串、数字文本和DBI下的undef
通常是这样工作的:
my $sth = $dbh->prepare('INSERT INTO t (a,b,c,d,e) VALUES (?,?,?,?,?)');
$sth->execute("'quoted'", 'null', undef, 123, "a string");
# Approximately the same as:
# INSERT INTO t (a,b,c,d,e) VALUES ('''quoted''', 'null', NULL, 123, 'a string');
# ^ ^ ^ ^ ^
# a string with quotes ----+ | | | |
# | | | |
# a string (not the NULL value) -------+ | | |
# | | |
# NULL (not the string 'null')----------------+ | |
# | |
# numeric literal ----------------------------------+ |
# |
# another string -----------------------------------------+
quote_identifier不仅有助于编码,它还允许列命名,例如
值
非常感谢这是一个更好的解决方案!quote_identifier不仅有助于编码,它还允许列命名,例如值
非常感谢这是一个更好的解决方案!quote_identifier不仅有助于编码,它还允许列命名,例如值
非常感谢这是一个更好的解决方案!quote_identifier不仅有助于编码,它还允许列命名,例如值
非常感谢这是一个更好的解决方案!