2016-04-08 95 views
0

t-sql中,可以运行多个select语句而不需要;。示例: select 1 select 2有效,并分别返回两个数据集12在单个PGexec调用中传递多个postgres SQL语句

postgres中,不可能运行多个select语句......您需要一个;分隔符,否则您会收到语法错误。

引用文档:http://www.postgresql.org/docs/current/interactive/libpq-exec.html

在单一的PQexec调用中发送多个查询在一个事务处理,除非有明确的开始/提交包含在查询字符串命令,把它分成多个事务。

我该怎么做?

比方说,我想运行这两个查询服务器上:select 1 select 2:它应该是这样的:

begin select 1 commit; begin select 2 commit

我确定它只是返回的最后一个查询的结果集,但我需要知道第一个查询是在服务器上执行的,即使它没有返回结果集。

为什么我要这样做:我有一个复杂的SQL脚本,它具有〜6个临时表来构建主查询将使用的表。通过使用;语法分隔临时表,我不能在cron中按计划运行此脚本。如果我可以运行临时表并运行主查询并在同一个PGexec调用中访问它们,我会非常高兴。

+0

从精细的手工HTTP://www.postgresql .org/docs/9.5/static/sql-createtable.html'在会话结束时或在当前事务结束时可以自动删除临时表(参见下面的ON COMMIT)。“ – wildplasser

+0

”By delimiting ..我无法调整在cron中使用这个脚本“ - 对不起,我很难理解这一点。为什么cron会受到.sql脚本文件中的内容的影响? –

+0

@RichardHuxton我有一个脚本,我想用'cron'来调度,这个脚本构建了一些临时表,然后对这些临时表运行查询。如果我使用';'终止,脚本将只执行第一个查询(第一个临时表),后续临时表/结果查询都不会运行 –

回答

1

我能够完成我一直在寻找对于CTE而不是临时表......一个长链CTE(充当临时表)对主要查询进行瀑布式分析。

一个简单的例子:

with first as (
    select 1 as col 
), 
second as (
    select 2 as col 
) 
select * from first union all select * from second 

更复杂的例子:

with COGS as (
    select 'Product1' Vertical, 3.0 Credit, 1.00 Debit, 2.75 Blend, 4.30 Amex, 0.25 ACH union 
    select 'Product2', 3.1, 2.2, 2.8, 4.5, 0.25 union 
), 
Allocable_Card_Volume as (
    select MPR.Date, sum(MPR.Card_Volume_Net_USD) Allocable_Card_Volume 
    from mpr_base MPR 
    where MPR.Gateway in ('YapProcessing') and MPR.Vertical not in ('HA-Intl','HA') 
    group by MPR.Date 
), 
COGS_Financials_Base as (
    select '2013-01-31'::DATE Date , 1000 Total_COGS , 200 Homeaway , (select Allocable_Card_Volume from Allocable_Card_Volume where Date in ('2013-01-31')) Allocable_Card_Volume union 
), 
Initial_COGS as (
    select 
     MPR.Date, 
     sum(
     case when MPR.PaymentTypeGroup in ('ACH_Scan','AmEx') then (Txn_Count * COGS.ACH) else 0 end + 
     case when MPR.Vertical not in ('HA') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') then 
           coalesce(((Credit_Card_Net_USD - Amex_Processing_Net_USD) * COGS.Credit * 0.01),0) + coalesce((Debit_Card_Net_USD * COGS.Debit * 0.01),0) + coalesce((Amex_Processing_Net_USD * COGS.Amex * 0.01),0) + coalesce((case when TPV is null and PaymentTypeGroup in ('Card') then TPV_Billing else 0 end * COGS.Blend * 0.01),0) 
        when MPR.Vertical in ('HA') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') and FeePaymentType in ('PropertyPaid') then 
           coalesce(COGS_Financials.Homeaway,0) 
           else 0 end 
     ) Initial_COGS 
    from 
     mpr_base MPR 
     left join COGS on COGS.Vertical = MPR.Vertical and MPR.Gateway in ('YapProcessing') and MPR.PaymentTypeGroup not in ('Cash') 
     left join COGS_Financials_Base COGS_Financials on MPR.Date = COGS_Financials.Date and MPR.Gateway in ('YapProcessing') and MPR.PaymentTypeGroup in ('Card') 
    where MPR.Gateway in ('YapProcessing') and MPR.Vertical not in ('HA-Intl') and MPR.PaymentTypeGroup not in ('Cash') 
    group by 
     MPR.Date 
), 
COGS_Financials as (
    select 
     COGS_Financials_Base.*, (COGS_Financials_Base.Total_COGS - Initial_COGS.Initial_COGS) Allocation 
    from 
     COGS_Financials_Base 
     join Initial_COGS on COGS_Financials_Base.Date = Initial_COGS.Date 
), 
MPR as (
    select 
     MPR.Date,MPR.Gateway,MPR.Vertical, MPR.ParentAccountId, MPR.ParentName , 
     MPR.PaymentTypeGroup , 
     sum(TPV_USD) TPV_USD, 
     sum(TPV_Net_USD) TPV_Net_USD, 
     sum(Revenue_Net_USD) Revenue_Net_USD , 
     sum(coalesce(
      case when MPR.PaymentTypeGroup in ('ACH_Scan','AmEx') then (Txn_Count * COGS.ACH) else 0 end + 
      case when MPR.Vertical not in ('HA') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') then 
        coalesce(((Credit_Card_Net_USD - Amex_Processing_Net_USD) * COGS.Credit * 0.01),0) + coalesce((Debit_Card_Net_USD * COGS.Debit * 0.01),0) + coalesce((Amex_Processing_Net_USD * COGS.Amex * 0.01),0) + coalesce((case when TPV is null and PaymentTypeGroup in ('Card') then TPV_Billing else 0 end * COGS.Blend * 0.01),0) 
       +(coalesce(((cast(Card_Volume_Net_USD as decimal(18,2))/cast(COGS_Financials.Allocable_Card_Volume as decimal(18,2))) * COGS_Financials.Allocation ), 0)) -- Excess 
         when MPR.Vertical in ('HA') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') and MPR.FeePaymentType in ('PropertyPaid') then coalesce(COGS_Financials.Homeaway,0) 
         else 0 
      end,0) 
     ) COGS_USD, 
     sum(Txn_Count) Txn_Count 
    from 
     mpr_Base MPR 
     left join COGS on COGS.Vertical = MPR.Vertical and MPR.Gateway in ('YapProcessing') and MPR.PaymentTypeGroup not in ('Cash') 
     left join COGS_Financials on MPR.Date = COGS_Financials.Date and MPR.Gateway in ('YapProcessing') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') 
    where 
     MPR.Date in ('2016-02-29') 
    group by 
     MPR.Date,MPR.Gateway,MPR.Vertical , MPR.ParentAccountId ,MPR.ParentName, 
     MPR.PaymentTypeGroup 
) 
select 
    Vertical, 
    sum(TPV_USD)::money as TPV_USD, 
    sum(Revenue_Net_USD)::money as Revenue_Net_USD, 
    sum(COGS_USD)::money COGS_USD, 
    round((sum(Revenue_Net_USD)-sum(COGS_USD))/sum(Revenue_Net_USD)*100,2) Accounting_Margin 
from 
    MPR 
where Date in ('2016-02-29') 
group by 
    Vertical 
union all 
select 
    'Total' , 
    sum(TPV_USD)::money as TPV_USD, 
    sum(Revenue_Net_USD)::money as Revenue_Net_USD, 
    sum(COGS_USD)::money COGS_USD, 
    round((sum(Revenue_Net_USD)-sum(COGS_USD))/sum(Revenue_Net_USD)*100,2) Accounting_Margin 
from 
    MPR 
where Date in ('2016-02-29') 

我说这将是复杂:-)

+0

这并不复杂。这是一个过于复杂的*结构*。 – wildplasser

0

你不LIBPQ,你可以用他psql的前端(在cron,您可能需要指定绝对路径为二进制)

#!/bin/sh 
psql -U my_user mydb <<OMG 
    begin; 
    select tralal 1; 
    commit; 

    begin; 
    select domtidom 2; 
    commit; 
OMG 
+0

任何我可以使用100%嵌入式SQL的方式,而不是使用'psql'工具?例如,在查询窗口中使用Postico GUI(或pgAdmin III)来发出'select 1 select 2'包裹在任何需要的语法,以便在服务器上执行两个查询? (&第一个查询的结果不必返回给客户端) –

+0

是的,您可以基于libpq构建一个前端。只需过滤掉注释,找到下一个';'并提交(注意字符串!)并检索结果并将其扔掉。将参数传递给准备好的查询将会更困难。但所有这些基本上就是'psql dbname /dev/null'所做的。 – wildplasser

+0

如果你想允许多个语句** WITHOUT **';'终止inbetween,你将需要一些最小类型的解析器(SQL不是LL(1),所以这不是一个漂亮的任务。顺序马尔可夫过滤器可以工作)祝你好运! – wildplasser