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

发布于 2024-08-06 17:16:18 字数 976 浏览 6 评论 0原文

不久前,我正在寻找 通过 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.

知道可能导致的原因这个?


EDIT to RET's & Petr's answers

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

我必须将其更改为这样,因为 die 命令会强制非自然死亡,并且该语句必须用单引号引起来。

A while back I was looking for a way to insert values into a text field through isql
and eventually found some load command that worked out for me.

It doesn't work when I try to execute it from Perl. I get a syntax error. I have tried two separate methods and both are not working so far.

I have the SQL statement variable print out at the end of each loop cycle so I know that the syntax is correct, but just not getting across correctly.

Here's the latest snip of code I was testing:

foreach(@files)
{

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

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

}

@files is an array whose elements are a full path/location of a pipe-delimited text file (ex. /home/xx/xx/xx/something.txt)

The number of columns in the table match the number of fields in the text file and the type-checking is fine (I've loaded test files manually without fail)

The error I get back is:

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

Any idea what might be causing this?


EDIT to RET's & Petr's answers

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

I had to change it to this, because the die command would force an unnatural death and the statement had to be wrapped in single quotes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

感情洁癖 2024-08-13 17:16:18

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。

希望这有帮助。

Petr is exactly right, the LOAD statement is an ISQL or DB-Access extension, so you can't execute it through DBI. If you have a look at the manual, you'll see it is also invalid syntax for SPL, ESQL/C and so on.

It's not clear whether you have to use perl to execute the script, or perl is just a convenient way of generating the SQL.

If the former, and you want a pure-perl method, you have to prepare an INSERT statement (there's just one table involved by the look of it?), and slurp through the file, using split to break it up into columns and executing the prepared insert.

Otherwise, you can generate the SQL using perl and execute it through DB-Access, either directly with system or by wrapping both in either a shell script or DOS batch file.

System call version

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

In a batch script version, you could write all the SQL into a single script, ie:

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

NB, the comment about quotes on the filename is only relevant if the filename contains spaces or metacharacters, the usual issue.

Also, one key difference in behaviour between isql and dbaccess is that when executed in this manner, dbaccess does not stop on error, but isql will. To make dbaccess stop processing on error, set DBACCNOIGN=1 in the environment.

Hope that's helpful.

感受沵的脚步 2024-08-13 17:16:18

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

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

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

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

This is because your query is not SQL query, it is an isql command that tells isql to parse the input file and generate INSERT statements.

If you think about it, the server can be on a completely different machine and has no idea what file are you talking about and how to access it.

So you basically have two options:

  1. call isql and pipe the LOAD command to it - very ugly
  2. parse the file yourself and generate the INSERT statements
可可 2024-08-13 17:16:18

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

正如其他人所说,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(?,?,?)”或“<代码>插入表值(?,?,?,?,?,?,?,?,?)'。您可以(可以说应该)在第二个列中包含列名称。

准备好后,您现在已经解析了卸载的数据。 SQLCMD 程序中有一个文档,可从 IIUG Software Archive 获取(该文档已在比微软的同名新贵程序长很多)。这非常详细地描述了 UNLOAD 格式。 Perl 能够处理 Informix 使用的任何内容 - 见证随 DBD::Informix 分发的 load.unload 文件中的 UNLOAD 信息。

Please note that the file Notes/load.unload is distributed with DBD::Informix and contains guidelines on how to handle UNLOAD operations using Perl, DBI and DBD::Informix. Somewhat to my chagrin, I see that it says "T.B.D." (more or less) for the LOAD section.

As other people have stated, the LOAD and UNLOAD statements are faked by various client-side tools to look like SQL statements, but the Informix server does not support them itself, mainly because of the issue with getting the file from a client machine (perhaps a PC) to the server machine (perhaps a Solaris machine).

To simulate the LOAD statement, you would need to analyze the INSERT INTO Table part. If it lists columns (INSERT INTO Table(Col03, Col05, Col09)), then you can expect three values in the load data file, and they go into those three columns. You would prepare a statement 'SELECT Col03, Col05, Col09 FROM Table' to get the types of the columns. Otherwise, you need to prepare a statement 'SELECT * FROM Table' to get the complete list of columns (and their types). Given the column names and the number of columns, you can create and prepare a suitable insert statement: 'INSERT INTO Table(Col03, Col05, Col09) VALUES(?,?,?)' or 'INSERT INTO Table VALUES(?,?,?,?,?,?,?,?,?)'. You could (arguably should) include column names in the second one.

With that ready, you now have parse the unloaded data. There is a document available in the SQLCMD program available from the IIUG Software Archive (which has been around a lot longer than Microsoft's upstart program of the same name). That describes the UNLOAD format in considerable detail. Perl has the ability to handle anything Informix uses - witness the UNLOAD information in the load.unload file distributed with DBD::Informix.

扎心 2024-08-13 17:16:18

快速谷歌搜索 显示 load 的语法 在文件名两边加上引号。如果您将语句更改为:

load from '$_' insert into some_table

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

A quick bit of Googling showed that the syntax for load puts quote marks around the file name. What if you change your statement to be:

load from '$_' insert into some_table

Since your statement is not using place holders, you have to put the quotes in yourself, as opposed to using the DBI quoting functionality.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文