代码之家  ›  专栏  ›  技术社区  ›  CheeseConQueso

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

  •  1
  • CheeseConQueso  · 技术社区  · 17 年前

    前一段时间我在找一个 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&pet的答案
    $STMT = "'LOAD FROM $_ INSERT INTO table'";
        system("echo $STMT | isql $db")
    

    我不得不把它改成这个,因为死亡命令会迫使一个不自然的死亡,声明必须用单引号包装。

    4 回复  |  直到 17 年前
        1
  •  2
  •   RET    17 年前

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

    不清楚您是否必须使用Perl来执行脚本,或者Perl只是生成SQL的一种方便方法。

    如果前者需要纯Perl方法,则必须准备一个insert语句(它的外观只涉及一个表?),然后使用 split 将它分解成列并执行准备好的插入。

    否则,您可以使用Perl生成SQL并通过DB访问执行它,或者直接使用 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在出错时停止处理,请在环境中设置dbacnoign=1。

    希望有帮助。

        2
  •  2
  •   Petr Topol    17 年前

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

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

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

    1. 调用isql并将加载命令发送给它-非常难看
    2. 自己分析文件并生成insert语句
        3
  •  2
  •   Jonathan Leffler    17 年前

    请注意文件 Notes/load.unload 与dbd::informix一起发布,并包含有关如何使用perl、dbi和dbd::informix处理卸载操作的指南。让我有点懊恼的是,我看到上面写着“T.B.D.”(或多或少)的负载部分。

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

    要模拟LOAD语句,需要分析 INSERT INTO Table 部分。如果它列出了列( INSERT INTO Table(Col03, Col05, Col09) ,然后您可以期望在加载数据文件中有三个值,它们将进入这三列。你要准备一份声明 SELECT Col03, Col05, Col09 FROM Table '以获取列的类型。否则,您需要准备一份声明' SELECT * FROM Table '以获取列(及其类型)的完整列表。给定列名和列数,可以创建和准备适当的insert语句:' INSERT INTO Table(Col03, Col05, Col09) VALUES(?,?,?) “或” INSERT INTO Table VALUES(?,?,?,?,?,?,?,?,?) '.可以(可以说应该)在第二个列中包含列名。

    准备好之后,您就可以解析卸载的数据了。sqlcmd程序中有一个文档可从 IIUG Software Archive (这比微软同名的新贵项目要长得多)。这相当详细地描述了卸载格式。Perl能够处理Informix使用的任何内容-见证 load.unload 使用dbd::informix分发的文件。

        4
  •  1
  •   Tony Miller    17 年前

    一点点谷歌搜索 showed that the syntax for load 在文件名周围加引号。如果你把你的陈述改成:

    load from '$_' insert into some_table
    

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

    推荐文章