2014-02-05 118 views
0

我想在使用DBI的perl中創建表。這是我的代碼:Perl DBI創建表錯誤

#! 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; 

我收到以下錯誤,當我運行此:

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. 

當我複製/粘貼在$直接在MySQL創建完全相同的字符串,它完美的作品。

請幫忙,謝謝。

編輯:對不起,我應該澄清。我拉從另一個來源$創建。這只是其中的一部分,我無法編輯文本。我想我需要知道如何將它分解成一個數組並逐個執行它們。

+3

某些db層不希望在同一步驟中執行多個查詢。無論如何,查詢看起來很正常。值得嘗試將大查詢字符串拆分爲不同的查詢。 –

+0

@LajosVeres是的,我試圖一次只分割成一個查詢,它的工作原理。問題是我將從另一個來源獲取這些數據,以上是一些創建表的示例,因此我將無法對其進行編輯,而且我不知道如何將其解析爲不同的變量。 – CircuitB0T

+0

然後嘗試用分號分割字符串並逐個執行它們。 –

回答

2

DBI連接不像MySQL命令行工具。一次不能執行多個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

如果來自外部的原始SQL拉動源是不是一個壞主意不夠,你總是可以使情況變得更糟:

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

的「MySQL的」和|管之間,你需要個e憑證--user =用戶名等,以及默認數據庫的名稱。

或者,對於DBI,如果SQL語句正確製作,就像mydqldump生成一樣,那麼;\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一起工作,因爲實際上有四個查詢,不是兩個:'如果存在DEVICE','CREATE TABLE DEVICE','drop table if exists SEGMENT'和'CREATE TABLE SEGMENT'。 – ThisSuitIsBlackNot

+0

看看發佈的$ create變量,drop語句用'--' – thekosmix

+0

註釋掉沒關係,沒有注意到你在循環內重新添加了'--'。如果你打算採取這種方法,分開';'更有意義,但噢。 – ThisSuitIsBlackNot