당신은 '상황'에 읽을 필요가 있고, 특히 '스칼라 컨텍스트'과 '배열 상황'이다. 당신은 스칼라 문맥을 제공하는
my $box_1 = @box1;
, 그리고 스칼라 문맥에서, @box1
배열의 요소 수를 반환
당신은 쓸 때. 당신이 썼다면 :
my($box_1) = @box1;
당신이 배열 컨텍스트를 제공 할 것이며, 배열 맥락에서, @box1
의 첫 번째 요소는 배열 컨텍스트, $box_1
의 첫 번째 요소에 할당 될 것이다 - 그리고 @box1
의 나머지 요소가 될 것이다 떨어졌다. (이 잘 당신이 계신 일 수있다. 당신이 @selectbox1
의 다양한 이름의 각각에 대한 하나의 ID 값을 선택하려고하는 것 같다)
당신이 $box_1
을 사용하려는 방법으로 판단하고 코드에서 $box_2
변수를 사용하는 경우 @box1
의 모든 값과 @box2
의 모든 값을 포함하는 단일 문자열을 얻으려는 경우 작은 따옴표로 묶인 DBI 드라이버에 제공해야합니다.
당신은 사용하여 문자열에 공백으로 구분 된 값을 얻을 수 있습니다 : 당신이 쉼표로 구분 된 값이 필요한 경우
my $box_1 = "@box1";
, 당신은 사용할 수 있습니다
my $box_1;
{ local $" = ","; $box_1 = "@box_1"; }
$"
(use English '-no_match_vars';
에서 일명 $LIST_SEPARATOR
를) 손상을 방지하기 위해 현지화해야합니다. 즉, $box_1
의 정의를 할당과 분리해야합니다. 그렇지 않으면를 떠날 때 $box_1
이 파괴됩니다.블록).
$box1 = $dbslave->quote($box1);
나 : 다음 SQL이 작동 할 수 있도록
이제
, 그것을 보호하기 위해, 당신은 quote
방법을 사용할 필요가 이러한 변경 사항을 조립
my $box1 = $dbslave->quote("@box1");
을, 우리가 얻을 :
#!/usr/bin/env perl
use strict;
use warnings;
### Improved, but not operational
# use DBI;
my @selectbox1 = ("group1", "group2", "group3");
my @selectbox2 = ("check1", "check2", "check3");
my $dbslave;
# $dbslave = DBI->connect(...) or die "A horrible death";
foreach my $select1 (@selectbox1)
{
my $sql_select1 = "select id from group_management where group_name = '$select1'";
my $box1 = $dbslave->prepare($sql_select1);
$box1->execute();
my @box1;
while (my $select_box1 = $box1->fetchrow_array())
{
push @box1, $select_box1;
}
my $box_1 = $dbslave->quote("@box1");
foreach my $select2(@selectbox2)
{
my $sql_select2 = "select id from checklist where checklist_name = '$select2'";
my $box2 = $dbslave->prepare($sql_select2);
$box2->execute();
my @box2;
while (my $select_box2 = $box2->fetchrow_array())
{
push @box2, $select_box2;
}
my $box_2 = $dbslave->quote("@box2");
my $sql_insert = "insert into checklist_group_mapping values ('', $box_2, $box_1)";
my $ins = $dbslave->prepare($sql_insert);
$ins->execute();
}
}
두 SELECT 문은 선택 상자 문자열에 Funn이 없다고 가정합니다. y 문자 (특히 작은 따옴표 없음). @selectbox1
및 @selectbox2
의 콘텐츠를 담당하고 있다면 괜찮습니다. 그들이 사용자 입력을 포함하고 있다면 그 입력을 위생 처리하거나 $dbslave->quote()
을 다시 사용하거나 자리 표시자를 사용해야합니다. 나는이 문제를 무시할 것이다.
$box1->fetchrow_array()
과 함께 스칼라 컨텍스트를 사용하고 있는데, 이는 사용자가 원하는 답변을 얻지 못할 수도 있습니다. (fetchrow_array()
은 상황에 따라 다르지만주의해야합니다.) 나는 다음과 같은 것을 사용할 것이다 :
my @box1;
while (my @row = $box1->fetchrow_array())
{
push @box1, $row[0];
}
my $box_1 = $dbslave->quote("@box1");
또한 함수를 사용해야한다.
my $sql_insert = "insert into checklist_group_mapping values ('', ?, ?)";
my $ins = $dbslave->prepare($sql_insert);
foreach my $select1 (@selectbox1)
{
my $sql_select1 = "select id from group_management where group_name = '$select1'";
my $box_1 = fetch_all($dbslave, $sql_select1);
foreach my $select2(@selectbox2)
{
my $sql_select2 = "select id from checklist where checklist_name = '$select2'";
my $box_2 = fetch_all($dbslave, $sql_select2);
$ins->execute($box_1, $box_2);
}
}
: 그것은 많은 시간을 한 번 준비하고 사용할 수 있도록 INSERT 문이 자리를 사용하도록 변환해야
#!/usr/bin/perl
use strict;
use warnings;
# use DBI;
my @selectbox1 = ("group1", "group2", "group3");
my @selectbox2 = ("check1", "check2", "check3");
my $dbslave;
# $dbslave = DBI->connect(...) or die "A horrible death";
sub fetch_all
{
my($dbh, $sql) = @_;
my $sth = $dbh->prepare($sql);
$sth->execute();
my @results;
while (my @row = $sth->fetchrow_array())
{
push @results, $row[0];
}
my $result = $dbslave->quote("@results");
return $result;
}
foreach my $select1 (@selectbox1)
{
my $sql_select1 = "select id from group_management where group_name = '$select1'";
my $box_1 = fetch_all($dbslave, $sql_select1);
foreach my $select2(@selectbox2)
{
my $sql_select2 = "select id from checklist where checklist_name = '$select2'";
my $box_2 = fetch_all($dbslave, $sql_select2);
my $sql_insert = "insert into checklist_group_mapping values ('', $box_2, $box_1)";
my $ins = $dbslave->prepare($sql_insert);
$ins->execute();
}
}
: 두 번 하나의 함수로 캡슐화 사용할 수있는 코드에서 눈부신 반복이있다
실제로 두 SELECT 문은 매개 변수화되고 한 번 준비되어 다시 사용해야합니다. 나는 그 변화를 보여주지 않았다. 왜냐하면 나는 게으르다. 그리고 (b) 더 큰 변화가 더 효과적이기 때문이다.
우리가 정말 무슨 일을하는지 볼 때, 모든 단일 SQL 문이어야한다 :
#!/usr/bin/perl
use strict;
use warnings;
# use DBI;
my @selectbox1 = ("group1", "group2", "group3");
my @selectbox2 = ("check1", "check2", "check3");
my $dbslave;
# $dbslave = DBI->connect(...) or die "A horrible death";
sub placeholder_list
{
my($n) = @_;
die "$n should be larger than 0" if $n <= 0;
my $list = "(?" . ",?" x ($n - 1) . ")";
return $list;
}
my $sql_insert = qq%
INSERT INTO checklist_group_mapping(col1, col2, col3)
SELECT '', gm.id, cl.id
FROM group_management AS gm
CROSS JOIN checklisst AS cl
WHERE gm.group_name IN X1
AND cl.checklist_name IN X2
%;
my $X1 = placeholder_list(scalar(@selectbox1));
my $X2 = placeholder_list(scalar(@selectbox2));
$sql_insert =~ s/X1/$X1/;
$sql_insert =~ s/X2/$X2/;
my $ins = $dbslave->prepare($sql_insert);
$ins->execute(@selectbox1, @selectbox2);
이의 가장 큰 장점은 응용 프로그램 사이에 흐르는 내용은 훨씬 적은 라운드 트립이 있다는 것입니다 (거의) 성능을 대폭 향상 시키며 대개 극적으로 데이터베이스에 영향을 미칩니다.
DBMS가 명시 적 CROSS JOIN을 지원하는지 여부 만 문제입니다. 그렇지 않으면 CROSS JOIN을 쉼표로 바꾸어야합니다.
준비된 문이 성공적으로 준비되었는지 확인하는 등의 수정해야 할 사항이 있습니다. 그러나 이것은 Perl에서 DBI를 사용하는 방법에 대한 통찰력을 줄 수 있습니다.
먼저 '자리 표시 자'를 사용하거나 추악 해집니다. 둘째,'$ dbslave'가 데이터베이스 핸들입니까? – hwnd
예 ... $ dbslave는 데이터베이스 핸들입니다. 그냥 삽입하고자하는 현재 값을 가져 오는 방법 : 다음 장소에서 수정이 필요합니다. my $ box_1 = @ box1 and my $ box_2 = @box2; –
DBI를 사용하고 있으며 오류가 있습니까? – hwnd