2016-04-08 32 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