PostgreSQL - пакет + скрипт + переменная - PullRequest
2 голосов
/ 23 декабря 2011

Я не программист, я немного борюсь с этим.

У меня есть пакетный файл, подключающийся к моему серверу PostgreSQL, и затем я открываю сценарий sql.Все работает как положено.У меня вопрос, как передать переменную (если возможно) от одного к другому.

Вот мой командный файл:

set PGPASSWORD=xxxx
cls
@echo off
C:\Progra~1\PostgreSQL\8.3\bin\psql -d Total -h localhost -p 5432 -U postgres -f C:\TotalProteinImport.sql

А вот сценарий:

copy totalprotein from 'c:/TP.csv' DELIMITERS ',' CSV HEADER;

update anagrafica
set pt=(select totalprotein.resultvalue from totalprotein where totalprotein.accessionnbr=anagrafica.id)
where data_analisi = '12/23/2011';

delete from totalprotein;

Это прекрасно работает, теперь вопрос в том, как я могу передать переменную, которая будет содержать дату для data_analisi?Как в пакетном файле «Пожалуйста, введите дату», а затем значение передается в сценарий sql.

Ответы [ 3 ]

2 голосов
/ 23 декабря 2011

psql поддерживает текстовые переменные замены. В пределах psql они могут быть установлены с помощью \set и использованы с помощью :varname.

\set xyz 'abcdef'
select :'xyz';
 ?column? 
----------
abcdef

Эти переменные также могут быть установлены с помощью аргументов командной строки:

psql -v xyz=value

Единственная проблема состоит в том, что эти текстовые замены всегда нуждаются в некоторой путанице с цитированием, как показано первыми \set и select.

2 голосов
/ 23 декабря 2011

Вы можете создать функцию из своего SQL-скрипта следующим образом:

CREATE OR REPLACE FUNCTION f_myfunc(date)
  RETURNS void AS
$BODY$

CREATE TEMP TABLE t_tmp ON COMMIT DROP AS
SELECT * FROM totalprotein LIMIT 0; -- copy table-structure from table

COPY t_tmp FROM 'c:/TP.csv' DELIMITERS ',' CSV HEADER;

UPDATE anagrafica a
SET    pt = t.resultvalue
FROM   t_tmp t
WHERE  a.data_analisi = $1
AND    t.accessionnbr = a.id;

-- Temp table is dropped automatically at end of session
-- In this case (ON COMMIT DROP) after the transaction

$BODY$
  LANGUAGE sql;

Вы можете использовать язык SQL для этого вида простого пакета SQL.

Как видите, я сделал несколько изменений в вашем скрипте, которые должны сделать его быстрее, чище и безопаснее.

Основные баллы

  • Для временного чтения данных в пустую таблицу используйте временную таблицу . Сохраняет много записей на диск и намного быстрее.

  • Для упрощения процесса я использую вашу существующую таблицу totalprotein в качестве шаблона для создания (пустой) временной таблицы.

  • Если вы хотите удалить все строки таблицы, используйте TRUNCATE вместо DELETE FROM. Намного быстрее. В данном конкретном случае вам не нужно ни того, ни другого. Временная таблица удаляется автоматически. Смотрите комментарии в функции.

  • Как вы обновили anagrafica.pt, вы бы установили для столбца NULL, если что-нибудь пойдет не так в процессе (date не найдено, неправильно date, id не найдено ...). Как я переписал ОБНОВЛЕНИЕ, это происходит только в том случае, если найдены соответствующие данные. Я предполагаю, что это то, что вы на самом деле хотите.

Затем запросите ввод данных пользователем в сценарии оболочки и вызовите функцию с датой в качестве параметра. Вот как это может работать в оболочке Linux (как пользовательские postgres, с доступом без пароля (используя метод IDENT в pg_haba.conf):

#! /bin/sh

# Ask for date. 'YYYY-MM-DD' = ISO date-format, valid with any postgres locale.
echo -n "Enter date in the form YYYY-MM-DD and press [ENTER]: "
read date

# check validity of $date ...
psql db -p5432 -c "SELECT f_myfunc('$date')"

-c заставляет psql выполнить отдельную команду SQL и затем завершить работу. Вчера я написал намного больше о psql и его параметрах командной строки в несколько связанном ответе.

Создание соответствующего пакетного файла Windows остается для вас упражнением.


Звонок под Windows

Сообщение об ошибке сообщает вам:

Функция tpimport (неизвестно) не существует

Обратите внимание на строчные буквы: tpimport. Я подозреваю, что вы использовали смешанные буквы для создания функции. Так что теперь вы должны заключать имя функции в двойные кавычки каждый раз, когда вы его используете.

Попробуйте это (отредактированные цитаты!):

C:\Progra~1\PostgreSQL\8.3\bin\psql -d Total -h localhost -p 5432 -U postgres
                                    -c "SELECT ""TPImport""('%dateimport%')"

Обратите внимание, как я использую одиночные и двойные кавычки здесь. Я думаю, это может работать под Windows. См здесь .

Вы затруднились для себя, когда решили использовать идентификаторы смешанного регистра в PostgreSQL - глупость, против которой я никогда не устаю предупреждать. Теперь вам нужно заключать в кавычки имя функции "TPImport" каждый раз, когда вы ее используете. Хотя это совершенно законно, я бы никогда не сделал бы это. Я использую строчные буквы для идентификаторов. Всегда. Таким образом, я никогда не путаю строчные и прописные буквы и никогда не использую двойные кавычки.

Окончательное исправление будет состоять в том, чтобы воссоздать функцию с именем в нижнем регистре (просто уберите двойные кавычки, и она будет автоматически свернута в нижний регистр). Тогда имя функции будет работать без кавычек.

Прочитайте основы об идентификаторах здесь .
Кроме того, стоит подумать, что обновление до более поздней версии PostgreSQL 8.3 немного устарело.

0 голосов
/ 11 ноября 2017

После создания функции в Postgres вы должны создать файл .bat в каталоге bin вашей версии Postgres, например C:\Program Files\PostgreSQL\9.3\bin. Здесь вы пишете:

@echo off
cd C:\Program Files\PostgreSQL\9.3\bin
psql -p 5432 -h localhost -d myDataBase -U postgres -c "select * from myFunction()"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...