2014-02-05 5 views
0

DBI를 사용하여 perl에서 테이블을 만들려고합니다. 내가/복사가 완벽하게 작동 mysql을 직접 만들 $에 동일한 문자열을 붙여 넣을 때Perl DBI 테이블 만들기 오류

DBD::mysql::st execute failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE TABLE SEGMENT(
ID    CHAR(100)  NOT NULL, 
DEVICE' at line 18 at file.pl line 47. 

:이 프로그램을 실행할 때 나는 다음과 같은 오류가

#! usr/bin/perl 
use strict; 
use warnings; 
use 5.014; 
use DBI; 

my $user = "user"; 
my $password = "password"; 
my $hostname = "localhost"; 
my $database = 'database'; 

my $dsn = "DBI:mysql:database=$database;host=$hostname;"; 
my $dbh = DBI->connect($dsn, $user, $password, { RaiseError => 1}); 


my $create = "-- drop table if exists DEVICE; 
CREATE TABLE DEVICE(
    NAME   CHAR(60), 
    ID   CHAR(36) NOT NULL, 
    SHORT_ID  INT UNSIGNED, 
    MODEL   CHAR(50), 
    SERIAL_NUMBER VARCHAR(50), 
    IP_ADDRESS CHAR(50), 
    LOCATION  CHAR(50), 
    DV_VERSION CHAR(20), 
    OS_VERSION CHAR(20), 
    DEVICE_GROUP CHAR(50), 
    MANAGED  TINYINT  NOT NULL, 
    CONSTRAINT PK_DEVICE PRIMARY KEY (ID) 
) Engine = InnoDB; 

-- drop table if exists SEGMENT; 
CREATE TABLE SEGMENT(
    ID    CHAR(100)  NOT NULL, 
    DEVICE_ID  CHAR(36)   NOT NULL, 
    NAME    CHAR(60), 
    IP_ADDRESS  CHAR(50), 
    SLOT_INDEX  INT NOT NULL, 
    SEGMENT_INDEX INT NOT NULL, 
    CONSTRAINT PK_SEGMENT PRIMARY KEY (ID), 
    KEY(DEVICE_ID), 
    CONSTRAINT FK_PARENT_DEV FOREIGN KEY (DEVICE_ID) REFERENCES DEVICE(ID) 
) Engine = InnoDB; 
"; 
my $sth = $dbh->prepare($create); 
$sth->execute; 

: 이것은 내 코드입니다.

감사합니다.

편집 : 죄송합니다. 분명히해야합니다. 다른 소스에서 $ create에있는 것을 가져옵니다. 이것은 그것의 일부일 뿐이며 텍스트를 편집 할 수 없습니다. 배열로 분할하고 하나씩 실행하는 방법을 알아야합니다.

+3

일부 db 계층은 동일한 단계에서 여러 쿼리를 실행하는 것을 원하지 않습니다. 어쨌든 쿼리는 정상적으로 보입니다. 큰 쿼리 문자열을 다른 쿼리로 분할하는 것이 좋습니다. –

+0

@LajosVeres 예, 한 번에 하나의 쿼리로 분할하려고 시도했지만 작동합니다.문제는 내가 다른 소스에서이 데이터를 가져올 것이며 위의 내용은 일부 테이블을 만드는 예일 뿐이므로 편집 할 수 없으며이를 다른 변수로 구문 분석하는 방법을 알지 못한다. . – CircuitB0T

+0

그런 다음 문자열을 세미콜론으로 분리하여 하나씩 실행 해보십시오. –

답변

2

DBI 연결이 MySQL 명령 줄 도구처럼 작동하지 않습니다. 하나 이상의 SQL 문을 실행할 수 없으며 접두어 --이 필요하지 않습니다.

는 (그것은 당신이 대문자 SQL 언어의 단어와 소문자 식별자의 규칙을 반대 한 것도 주목할만한입니다.) 외부에서 원시 SQL 당기는 경우,이 같은

코드

$dbh->do("drop table if exists DEVICE"); 
$dbh->do(<<__ENDSQL__); 
CREATE TABLE DEVICE(
    NAME   CHAR(60), 
    ID   CHAR(36) NOT NULL, 
    SHORT_ID  INT UNSIGNED, 
    MODEL   CHAR(50), 
    SERIAL_NUMBER VARCHAR(50), 
    IP_ADDRESS CHAR(50), 
    LOCATION  CHAR(50), 
    DV_VERSION CHAR(20), 
    OS_VERSION CHAR(20), 
    DEVICE_GROUP CHAR(50), 
    MANAGED  TINYINT  NOT NULL, 
    CONSTRAINT PK_DEVICE PRIMARY KEY (ID) 
) Engine = InnoDB 
__ENDSQL__ 

$dbh->do("drop table if exists SEGMENT"); 
$dbh->do(<<__ENDSQL__); 
CREATE TABLE SEGMENT(
    ID    CHAR(100)  NOT NULL, 
    DEVICE_ID  CHAR(36)   NOT NULL, 
    NAME    CHAR(60), 
    IP_ADDRESS  CHAR(50), 
    SLOT_INDEX  INT NOT NULL, 
    SEGMENT_INDEX INT NOT NULL, 
    CONSTRAINT PK_SEGMENT PRIMARY KEY (ID), 
    KEY(DEVICE_ID), 
    CONSTRAINT FK_PARENT_DEV FOREIGN KEY (DEVICE_ID) REFERENCES DEVICE(ID) 
) Engine = InnoDB 
__ENDSQL__ 
+0

죄송합니다. API에서 가져 왔으며이 형식을 편집 할 수 없다는 것을 언급해야합니다. – CircuitB0T

+0

@ CircuitB0T 전체 DDL을 하나의 큰 문자열 값으로 가져온 다음 다른 응답을 제안 할 때이를 분리하십시오. 그러나 ** do **로 여기에 표시된대로 문장을 실행하십시오. –

0

작동합니다 소스가 나쁜만큼 생각이 아닙니다, 당신은 항상 더 나쁘게 만들 수 :은 "MySQL은"및 | 파이프 사이

open my $fh, "mysql |"; 
print $fh "$create\n"; 
close $fh; 

을, 당신은 일해야합니다 e 자격 증명 --user = username 등, 기본 데이터베이스의 이름.

또는 DBI를 사용하면 mydqldump가 생성하는 것처럼 SQL 문이 올바르게 작성된 경우 ;\n이 항상 명령문 구분 기호가되므로 합리적으로 행운을 나누어 문자열을 분할해야합니다 ... 사실, 세미콜론 - MySQL은 실제로 신경 쓰지 않습니다.

DELIMITER 선언이 선행 된 저장 프로 시저와 같은 복잡한 것이 있으면 해당 구문을 구문 분석하고 이에 따라 구분 기호에 대한 기대치를 수정하고 구분 기호와 대체 구분 기호를 삭제해야합니다. 구분 기호 선언과 사용자 정의 구분 기호를 DBI와 함께 사용할 필요가 없으며 실제로 사용할 수 없습니다. 단지 -> do() 호출에서 프로 시저 선언을 보내면 작동합니다.

구분 기호를 분리하면 ...주석 줄을 제거 할 수 있어야합니다. 주석은 제거 할 필요가 없습니다. 당신이 바로 모든 것을, 단지 약간의 변화를하고있는

1

는 별도로 두 쿼리를 실행, $create 후이 코드를 넣어 :

my $delim = "-- "; // delimeter 
my @sqls = split($delim, $create); //split based on delimiter 

foreach my $sql (@sqls) { // take each sql string 
     $sql = $delim . $sql; // append delimiter, as it was removed while splitting the sql string 
     my $sth = $dbh->prepare($sql); // prepare the sql statement 
     $sth->execute; // execute it 
} 

exit 0; 

PS :이는 테스트 코드입니다.

+0

실제로 OP가 게시 된 SQL로 작업하는 것을 상상할 수 없습니다. 실제로 '테이블이 존재하면 드롭 테이블', '테이블 생성 장치', '테이블이 존재하면 드롭 테이블', 그리고 '생성 TABLE SEGMENT'를 참조하십시오. – ThisSuitIsBlackNot

+0

게시 된 $ create 변수를 살펴보면, drop 문은'--'로 주석 처리됩니다. – thekosmix

+0

신경 쓰지 마세요. 루프 안에'--'를 다시 추가했음을 알지 못했습니다. 이 접근법을 사용한다면,';'로 분리하는 것이 더 의미가 있지만, 오 잘. – ThisSuitIsBlackNot