为什么这个ISQL命令不会通过Perl的DBI运行?

时间:2009-10-02 19:18:01

标签: perl informix dbi syntax-error

前段时间我正在寻找一个way to insert values into a text field through isql 并最终找到了一些适合我的加载命令。

当我尝试从Perl执行它时,它不起作用。我收到语法错误。我尝试了两种不同的方法,到目前为止两种方法都不起作用。

我在每个循环周期结束时打印出SQL语句变量,所以我知道语法是正确的,但是没有正确接触。

这是我正在测试的最新代码片段:

foreach(@files)
{

$STMT = <<EOF;
load from $_ insert into some_table
EOF

$sth = $db1->prepare($STMT);
$sth->execute;

}

@files是一个数组,其元素是竖线分隔文本文件的完整路径/位置(例如/home/xx/xx/xx/something.txt)

表中的列数与文本文件中的字段数相匹配,并且类型检查正常(我已手动加载测试文件)

我得到的错误是:

DBD::Informix::db prepare failed: SQL: -201: A syntax error has occurred.

知道可能导致这种情况的原因是什么?

<小时/> 编辑RET和&amp;彼得的回答

$STMT = "'LOAD FROM $_ INSERT INTO table'";
    system("echo $STMT | isql $db")

我不得不将其更改为此,因为die命令会导致非自然死亡,并且声明必须用单引号括起来。

4 个答案:

答案 0 :(得分:2)

这是因为您的查询不是SQL查询,它是一个isql命令,它告诉isql解析输入文件并生成INSERT语句。

如果你考虑一下,服务器可以在一台完全不同的机器上,不知道你在说什么文件以及如何访问它。

所以你基本上有两个选择:

  1. 调用isql并将LOAD命令传递给它 - 非常难看
  2. 自己解析文件并生成INSERT语句

答案 1 :(得分:2)

Petr完全正确,LOAD语句是ISQL或DB-Access扩展,因此您无法通过DBI执行它。如果你看一下手册,你会发现它也是SPL,ESQL / C等的无效语法。

目前尚不清楚是否必须使用perl来执行脚本,或者perl只是一种生成SQL的便捷方式。

如果是前者,并且你想要一个纯perl方法,你必须准备一个INSERT语句(它的外观只涉及一个表?),然后使用split来覆盖整个文件将其分解为列并执行准备好的插入。

否则,您可以使用perl生成SQL并通过DB-Access执行它,可以直接使用system,也可以将它们包装在shell脚本或DOS批处理文件中。

系统调用版

foreach (@files) {
    my $stmt = "LOAD FROM $_ INSERT INTO table;\n";
    system("echo $stmt | dbaccess $database")
            || die "Statement $stmt failed: $!\n";
}

在批处理脚本版本中,您可以将所有SQL写入单个脚本,即:

perl -e 'while(@ARGV){shift; print "LOAD FROM '$_' INSERT INTO table;\n"}' file1 [ file2 ... ] > loadfiles.sql
isql database loadfiles.sql

注意,关于文件名的引用的注释仅在文件名包含空格或元字符时才是相关的,这是常见的问题。

另外,isql和dbaccess之间的一个主要区别在于,当以这种方式执行时,dbaccess不会因错误而停止,但isql会停止。要使dbaccess在出错时停止处理,请在环境中设置DBACCNOIGN = 1。

希望这有帮助。

答案 2 :(得分:2)

请注意,文件Notes/load.unload随DBD :: Informix一起分发,并包含有关如何使用Perl,DBI和DBD :: Informix处理UNLOAD操作的指南。有点令我懊恼,我看到它说“T.B.D.” (或多或少)LOAD部分。

正如其他人所说,LOAD和UNLOAD语句被各种客户端工具伪造成看起来像SQL语句,但Informix服务器本身并不支持它们,主要是因为从客户端获取文件的问题机器(可能是PC)到服务器机器(可能是Solaris机器)。

要模拟LOAD语句,您需要分析INSERT INTO Table部分。如果它列出了列(INSERT INTO Table(Col03, Col05, Col09)),那么您可以在加载数据文件中看到三个值,它们会进入这三列。您可以准备一个语句“SELECT Col03, Col05, Col09 FROM Table”来获取列的类型。否则,您需要准备一个语句“SELECT * FROM Table”以获取列的完整列表(及其类型)。给定列名称和列数,您可以创建并准备合适的插入语句:“INSERT INTO Table(Col03, Col05, Col09) VALUES(?,?,?)”或“INSERT INTO Table VALUES(?,?,?,?,?,?,?,?,?)”。您可以(可以说应该)在第二个列中包含列名。

准备就绪后,您现在可以解析卸载的数据。 SQLCMD程序中提供了一个文档,可从IIUG Software Archive获得(它的版本比微软的同名新手程序长得多)。这相当详细地描述了UNLOAD格式。 Perl能够处理Informix使用的任何内容 - 见证与DBD :: Informix一起分发的load.unload文件中的UNLOAD信息。

答案 3 :(得分:1)

快速搜索一下Google showed that the syntax for load会在文件名周围加上引号。如果您将声明更改为:

,该怎么办?
load from '$_' insert into some_table

由于您的声明不使用占位符,因此您必须自行引用引号,而不是使用DBI引用功能。