为什么这个 ISQL 命令不能通过 Perl 的 DBI 运行?
不久前,我正在寻找 通过 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Petr 完全正确,LOAD 语句是 ISQL 或 DB-Access 扩展,因此您不能通过 DBI 执行它。如果你看一下手册,你会发现它对于 SPL、ESQL/C 等也是无效的语法。
目前尚不清楚是否必须使用 perl 来执行脚本,或者 perl 只是生成 SQL 的一种便捷方法。
如果是前者,并且您想要一个纯 Perl 方法,则必须准备一条 INSERT 语句(从它的外观来看,只涉及一个表?),然后使用
split
读取文件将其分成列并执行准备好的插入。否则,您可以使用 perl 生成 SQL 并通过 DB-Access 执行它,可以直接使用
system
或将两者包装在 shell 脚本或 DOS 批处理文件中。系统调用版本
在批处理脚本版本中,您可以将所有 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
In a batch script version, you could write all the SQL into a single script, ie:
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.
这是因为您的查询不是 SQL 查询,而是一个 isql 命令,告诉 isql 解析输入文件并生成 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:
请注意,文件
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.快速谷歌搜索 显示 load 的语法 在文件名两边加上引号。如果您将语句更改为:
由于您的语句不使用占位符,因此您必须自己添加引号,而不是使用 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:
Since your statement is not using place holders, you have to put the quotes in yourself, as opposed to using the DBI quoting functionality.