2016-04-08 8 views
0

t-sqlには、;なしで複数のselect文を実行することができます。例: select 1 select 2が有効であり、それぞれ12という2つのデータセットを返します。複数のpostgres SQL文を1回のPGexec呼び出しで渡す

postgresでは、select文を複数実行することはできません... ;区切り文字が必要です。そうしないと、構文エラーが発生します。ドキュメントを参照

:明示的なBEGIN/COMMITコマンドがある場合を除き、単一のPQexecの実行呼び出しで送信されhttp://www.postgresql.org/docs/current/interactive/libpq-exec.html

複数のクエリは、単一のトランザクションで処理されているが、複数のトランザクションに分割するために、クエリ文字列に含まれています。

どうすればいいですか? select 1 select 2

のは、私は、サーバー上でこれらの2つのクエリを実行したいとしましょう、それは次のようになります。

begin select 1 commit; begin select 2 commit

は、私はそれが唯一の結果セットとして最後のクエリを返すとOKだけど、最初のクエリがその結果セットで返されていなくても、サーバー上で実行されたことを知る必要があります。

私はこれをやりたいのです:メインクエリが使用するビルドする〜6つの一時テーブルを持つ複雑なSQLスクリプトがあります。 ;の構文でテンポラリテーブルを区切ることで、cronでこのスクリプトをスケジュール設定することはできません。同じテーブルPGexecで呼び出すために実行する一時テーブルとメインクエリを取得できる場合、非常に満足しています。あなたはlibpqをしていない

+0

だろう言った://www.postgresql .org/docs/9.5/static/sql-createtable.html 'テンポラリテーブルは、セッションの終了時、またはオプションで現在のトランザクションの終了時に自動的に削除されます(ON COMMITを参照してください)。" – wildplasser

+0

"区切りで私はスケジュールできませんuleこのスクリプトはcronで " - 申し訳ありませんが、私はこれを理解するのに苦労しています。なぜcronは.sqlスクリプトファイルにあったのか? –

+0

@RichardHuxton私は 'cron'でスケジュールしたいスクリプトを用意していますが、このスクリプトはいくつかの一時テーブルを作成し、それらの一時テーブルに対してクエリを実行します。私が ';'終了を使用すると、スクリプトは最初のクエリ(最初の一時テーブル)のみを実行します。後続の一時テーブル/結果クエリは実行されません –

答えて

1

をのpsql使用することができます私は私が探していたものを達成することができましたテンポラリテーブルではなくCTEを使用している場合...メインクエリにウォーターフォールするCTEの1つの長鎖(一時テーブルとして機能する)。

簡単な例:

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') 

私はそれは細かいマニュアルのhttpから複雑な:-)

+0

これは複雑ではありません。これはあまりにも複雑な構造*です。 – wildplasser

0

は、あなただけの彼は、フロントエンド(クーロンで、あなたがバイナリの絶対パス名を指定する必要がある場合があります)

#!/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

そして、複数のステートメントを許可する場合は、最小限の種類のパーサーが必要です(SQLはLL(1)ではないので、これはかなりの作業ではありません)。注文マルコフフィルタが動作する可能性があります)幸運を! – wildplasser

関連する問題