1

不久前,我正在寻找一种通过 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 和 Petr 的答案

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

我不得不把它改成这个,因为 die 命令会强制非自然死亡,并且语句必须用单引号括起来。

4

4 回答 4

2

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

如果您考虑一下,服务器可能位于完全不同的机器上,并且不知道您在谈论什么文件以及如何访问它。

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

  1. 调用 isql 并将 LOAD 命令传递给它 - 非常难看
  2. 自己解析文件并生成 INSERT 语句
于 2009-10-02T19:53:28.250 回答
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。

希望这会有所帮助。

于 2009-10-03T06:58:19.070 回答
2

请注意,该文件Notes/load.unload与 DBD::Informix 一起分发,并包含有关如何使用 Perl、DBI 和 DBD::Informix 处理 UNLOAD 操作的指南。让我有些懊恼的是,我看到 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(?,?,?,?,?,?,?,?,?)'。您可以(可以说应该)在第二个中包含列名。

准备就绪后,您现在已经解析了卸载的数据。IIUG Software Archive提供的 SQLCMD 程序中有一个文档(它的存在时间比 Microsoft 的同名新贵程序要长得多)。这相当详细地描述了 UNLOAD 格式。Perl 有能力处理 Informix 使用的任何东西——见证load.unload与 DBD::Informix 一起分发的文件中的 UNLOAD 信息。

于 2009-10-04T01:30:06.020 回答
1

快速谷歌搜索表明 load 的语法在文件名周围加上引号。如果您将声明更改为:

load from '$_' insert into some_table

由于您的语句没有使用占位符,因此您必须自己加上引号,而不是使用 DBI 引用功能。

于 2009-10-02T19:29:19.060 回答