Почему эта команда ISQL не запускается через DBI Perl? - PullRequest
1 голос
/ 02 октября 2009

Некоторое время назад я искал способ вставить значения в текстовое поле через 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 ]

2 голосов
/ 04 октября 2009

Обратите внимание, что файл Notes/load.unload распространяется с DBD :: Informix и содержит рекомендации о том, как обрабатывать операции UNLOAD с использованием Perl, DBI и DBD :: Informix. К моему большому огорчению, я вижу, что там написано "Т.Б.Д." (более или менее) для секции LOAD.

Как утверждают другие люди, операторы LOAD и UNLOAD подделываются различными инструментами на стороне клиента, чтобы выглядеть как операторы SQL, но сервер Informix не поддерживает их сам, в основном из-за проблемы с получением файла от клиента. компьютер (возможно, ПК) на сервер (возможно, компьютер 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 (который был намного дольше, чем программа Microsoft с таким же названием). Это описывает формат UNLOAD в значительной степени. Perl имеет возможность обрабатывать все, что использует Informix - засвидетельствуйте информацию UNLOAD в файле load.unload, распространяемом вместе с DBD :: Informix.

2 голосов
/ 02 октября 2009

Это потому, что ваш запрос не является запросом SQL, это команда isql, которая сообщает isql, что нужно проанализировать входной файл и сгенерировать операторы INSERT.

Если подумать, сервер может находиться на совершенно другой машине, и он не знает, о каком файле вы говорите и как получить к нему доступ.

Итак, у вас есть два варианта:

  1. вызовите isql и передайте ему команду LOAD - очень уродливо
  2. разберите файл самостоятельно и сгенерируйте операторы INSERT
2 голосов
/ 03 октября 2009

Петр совершенно прав, оператор LOAD является расширением ISQL или DB-Access, поэтому вы не можете выполнить его через DBI. Если вы посмотрите руководство, вы увидите, что он также является недопустимым синтаксисом для SPL, ESQL / C и т. Д.

Не ясно, нужно ли использовать Perl для выполнения скрипта, или Perl - это просто удобный способ генерации SQL.

Если первый и вам нужен метод чистого perl, вы должны подготовить оператор INSERT (на его взгляд задействована только одна таблица?) И просмотреть файл, используя split, чтобы разбить его. в столбцы и выполнение подготовленной вставки.

В противном случае вы можете сгенерировать SQL с помощью perl и выполнить его через DB-Access, либо напрямую с помощью system, либо обернув оба в сценарий оболочки или пакетный файл 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.

Надеюсь, это полезно.

1 голос
/ 02 октября 2009

Быстрый поиск в Google показал, что синтаксис для загрузки ставит кавычки вокруг имени файла. Что если вы измените свое заявление на:

load from '$_' insert into some_table

Поскольку в вашем заявлении не используются заполнители, вы должны сами заключать в кавычки, а не использовать функцию цитирования DBI.

...