【问题标题】:PostgreSQL - batch + script + variablePostgreSQL - 批处理 + 脚本 + 变量
【发布时间】:2012-01-26 22:27:25
【问题描述】:

我不是程序员,我在这方面有点挣扎。

我有一个批处理文件连接到我的 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 脚本。

【问题讨论】:

  • 标志被移除,请参考FAQ。

标签: postgresql variables batch-file


【解决方案1】:

您可以像这样从您的 SQL 脚本中create a function

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 批处理可以使用language SQL

如您所见,我对您的脚本进行了一些修改,以使其更快、更清晰、更安全。

要点

  • 要临时将数据读入空表,请使用temporary table。节省大量磁盘写入,速度更快。

  • 为了简化流程,我使用您现有的表 totalprotein 作为创建(空)临时表的模板。

  • 如果要删除表的所有行,请使用 TRUNCATE 而不是 DELETE FROM。快多了。在这种特殊情况下,您都不需要。临时表会自动删除。见函数中的 cmets。

  • 您更新anagrafica.pt 的方式将列设置为NULL,如果在此过程中任何事情 出错(date 未找到,错误date,@ 987654334@ 未找到...)。我重写 UPDATE 的方式,只有在找到匹配的数据时才会发生。我想这就是你真正想要的。

然后在您的 shell 脚本中请求用户输入并以日期作为参数调用该函数。这就是它在 Linux shell 中的工作方式(作为用户 postgres,具有无密码访问权限(使用 pg_haba.conf 中的 IDENT 方法):

#! /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 and its command line options 上写了很多相关的答案。

创建相应的 Windows 批处理文件仍然是您的练习。


Windows下调用

错误信息告诉你:

函数 tpimport(unknown) 不存在

注意小写字母:tpimport。我怀疑您使用混合大小写字母来创建函数。所以现在每次使用函数名时都必须用双引号括起来。

试试这个(编辑过的引号!):

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

请注意我在这里如何使用单引号和双引号。我这可以在 Windows 下工作。见here

当您选择在 PostgreSQL 中使用 混合大小写标识符 时,您自己很难受 - 这是我从不厌倦警告的愚蠢行为。现在你必须在每次使用函数名"TPImport" 时将其双引号。虽然完全合法,但我永远不会这样做。我使用小写字母作为标识符。总是。这样我就不会混淆小写/大写,也不必使用双引号。

最终修复是用小写名称重新创建函数(只需去掉双引号,它将自动折叠为小写)。然后函数名称将无需任何引用即可正常工作。

阅读basics about identifiers here
另外,考虑升级到更新版本的 PostgreSQL 8.3 现在有点生疏了。

【讨论】:

  • 感谢 Erwin 提供的所有信息!现在...看起来当我从 PGAdmin 调用该函数时,它运行正常。如果我尝试从我的批处理文件中运行它,它会说该函数不存在。函数需要写在哪里?现在我在我的数据库“Schema”、“Public”、“Functions”下拥有它。但看起来这在 psql -c "SELECT "myfunction"('%dateimport%')" 中是不可用的。同样的命令在 pgadmin 中工作得很好(输入一个特定的日期)。
  • @damien:您需要像我在代码示例中所做的那样提供数据库的名称:psql db -c "SELECT myfunction('%dateimport%')"。如果不这样做,您将连接到名称为postgres 的默认维护数据库,并且在那里找不到该功能。此外,不要在函数名称周围包含一对双引号。它破坏了引用。
  • Erwin,对不起,我没有写完整的细节......整个命令行是:C:\Progra~1\PostgreSQL\8.3\bin\psql -d Total -h localhost -p 5432 -U postgres -c "SELECT "TPImport"('%dateimport%')"。我删除了引号,但出现了同样的问题,“函数 tpimport(unknown) 不存在”,然后是“LINE1: SELECT TPImport('12/27/2011')”。 “提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。” PGAdmin 中带有引号的同一行 SELECT "TPImport"('12/27/2011') 工作正常...
  • 我修好了!感谢欧文的帮助!问题是,通过 pgadmin 的“新函数”创建函数,它会将其创建为:CREATE OR REPLACE FUNCTION "tpimport"(dateimport timestamp without time zone) RETURNS void AS etc.... 我删除了函数,并创建了再次通过 SQL 语句“CREATE OR REPLACE FUNCTION tpimport(dateimport timestamp without time zone) RETURNS void AS etc...”。删除 tpimport 周围的引号有效。实际上我之前在创建表时遇到了同样的问题......通过 pgadmin 它在表名周围使用引号,这使得它们
  • @damien:我的建议是从不在标识符周围使用双引号并始终使用小写字母。让您的生活更轻松。 :) 但是,在这种情况下 .. "tpimport" .. 全部小写 .. 双引号无效.. 开始没问题。没关系,它有效。
【解决方案2】:

psql 支持文本替换变量。在psql 中,它们可以使用\set 设置并使用:varname 使用。

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

这些变量也可以使用命令行参数设置:

psql -v xyz=value

唯一的问题是这些文本替换总是需要一些引用,如第一个 \setselect 所示。

【讨论】:

    【解决方案3】:

    在 Postgres 中创建函数后,您必须在 Postgres 版本的 bin 目录中创建一个 .bat 文件,例如 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()"
    

    【讨论】:

      猜你喜欢
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      • 1970-01-01
      • 1970-01-01
      • 2014-02-10
      • 2018-11-03
      相关资源
      最近更新 更多