簡體   English   中英

Perl DBI創建表錯誤

[英]Perl DBI create table error

我正在嘗試使用DBI在perl中創建表。 這是我的代碼:

#! 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中復制/粘貼$ create中完全相同的字符串時,它可以完美地工作。

請幫忙,謝謝。

編輯:對不起,我應該澄清一下。 我從另一個來源獲取$ create中的內容。 這只是其中的一部分,我無法編輯文本。 我想我需要知道如何將其拆分為一個數組並一個接一個地執行它們。

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__

您所做的一切都正確,只是稍作更改,分別執行這兩個查詢,並將此代碼放在$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:這是經過測試的代碼。

如果從外部來源引入原始sql並不是一個壞主意,那么您總可以使其更糟:

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

在“ mysql”和“ | 管道,您需要憑據--user = username等,以及默認數據庫的名稱。

或者,對於DBI,如果像mydqldump生成那樣正確地構造了SQL語句,則;\\n將始終是語句定界符,因此您應該有足夠的運氣來分割字符串...實際上,您甚至可以丟棄分號。 -MySQL實際上並不在乎。

如果您有任何更復雜的事情,例如在DELIMITER聲明之前的存儲過程,則需要解析這些語句,相應地修改對定界符的期望,並丟棄定界符語句以及備用定界符。 您不需要,實際上也不能使用DBI的分隔符聲明和自定義分隔符-您只需在一個-> do()調用中發送過程聲明,它就可以工作。

一旦在分隔符上進行分割,您應該能夠按原樣使用--注釋行,而不必刪除那些分隔符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM