복붙노트

[SQL] 어떻게 DO 블록에서 선택 쿼리를 수행하기 위해?

SQL

어떻게 DO 블록에서 선택 쿼리를 수행하기 위해?

나는 포트에 PostgreSQL을에 MS SQL-Server에서 SQL 아래 코드를 원한다.

DECLARE @iStartYear integer
DECLARE @iStartMonth integer

DECLARE @iEndYear integer
DECLARE @iEndMonth integer

SET @iStartYear = 2012
SET @iStartMonth = 4

SET @iEndYear = 2016
SET @iEndMonth = 1


;WITH CTE 
AS
(
    SELECT 
         --@iStartYear AS TheStartYear 
         @iStartMonth AS TheRunningMonth 
        ,@iStartYear AS TheYear  
        ,@iStartMonth AS TheMonth 

    UNION ALL 

    SELECT 
         --CTE.TheStartYear AS TheStartYear 
         --@iStartYear AS TheStartYear 
         CTE.TheRunningMonth + 1 AS TheRunningMonth 
         --,CTE.TheStartYear + (CTE.TheRunningMonth / 12) AS TheYear 
        ,@iStartYear + (CTE.TheRunningMonth / 12) AS TheYear 
        ,(CTE.TheMonth + 1 -1) % 12 + 1 AS TheMonth
    FROM CTE 
    WHERE (1=1) 

    AND
    (
        CASE 
            --WHEN (CTE.TheStartYear + (CTE.TheRunningMonth / 12) ) < @iEndYear 
            WHEN (@iStartYear + (CTE.TheRunningMonth / 12) ) < @iEndYear 
                THEN 1 
            --WHEN (CTE.TheStartYear + (CTE.TheRunningMonth / 12) ) = @iEndYear 
            WHEN (@iStartYear + (CTE.TheRunningMonth / 12) ) = @iEndYear 
                THEN 
                    CASE 
                        WHEN ( (CTE.TheMonth + 1 -1) % 12 + 1 ) <= @iEndMonth 
                            THEN 1 
                        ELSE 0 
                    END 
            ELSE 0 
        END = 1 
    )
)
SELECT * FROM CTE 

이것은 내가 지금까지있는 것입니다.

DO $$
    DECLARE r record;
    DECLARE i integer;

    DECLARE __iStartYear integer;
    DECLARE __iStartMonth integer;

    DECLARE __iEndYear integer;
    DECLARE __iEndMonth integer;

    DECLARE __mytext character varying(200);
BEGIN
    i:= 5;

    --RAISE NOTICE  'test'
    --RAISE NOTICE  'test1' || 'test2';

    __mytext := 'Test message';
    --RAISE NOTICE __mytext;
    RAISE NOTICE '%', __mytext;
    RAISE NOTICE '% %', 'arg1', 'arg2';

    --SQL Standard:  "CAST( value AS text )" [or varchar]
    --PostgreSQL short-hand:  "value::text"
    __mytext := 'Test ' || i::text;
    RAISE NOTICE '%', __mytext;

    __mytext := 'mynumber: ' || CAST(i as varchar(33)) || '%';
    RAISE NOTICE '%', __mytext;

    __iStartYear := 2012;
    __iStartMonth := 4;

    __iEndYear := 2016;
    __iEndMonth := 1;

    --PERFORM  'abc';
    SELECT 'abc';

    -- SELECT  __iStartMonth AS TheRunningMonth; 


    -- RAISE NOTICE  'The raise_test() function began.' + CAST( i AS text ) ;
    -- FOR r IN SELECT table_schema, table_name FROM information_schema.tables WHERE table_type = 'VIEW' AND table_schema = 'public'
    -- LOOP
    --  EXECUTE 'GRANT ALL ON ' || quote_ident(r.table_schema) || '.' || quote_ident(r.table_name) || ' TO webuser';
    --END LOOP;
END$$;

당신이 볼 수 있듯이 인상 통지 기능을 갖춘 '인쇄'에 원하는 때, 나는 몇 가지 문제가 있었다. 하지만 구글이를 해결하기 위해 관리.

이전의 경험에서, 나는 유일한 진짜 문제는 내가이 필요한 블록을 할 수있는 몇 가지 변수를 정의해야한다는 것입니다, 그래서에만 CTE 전에 재귀를 추가해야 CTE의와 포스트 그레스 구문은 매우 유사 나는 것을 알 수 있습니다.

이 간단한 질문 결과에서 나는 가지고 : 어떻게 DO 블록에서 선택 쿼리를 "수행"할 수 있습니까? 나는 pgAdmin3의 '데이터 출력'탭에서 결과를보고 싶어요. 그리고 함수를 작성하고 싶지 않아요.

해결법

  1. ==============================

    1.할 일 명령 행을 반환하지 않습니다. 당신은 공지 사항 또는 (언어 plpgsql와) RAISE 다른 메시지를 보낼 수 있습니다 또는 당신은 (임시) 테이블을 작성하고 나중에이 문제를 해결하기 위해 그것에서 선택할 수 있습니다.

    할 일 명령 행을 반환하지 않습니다. 당신은 공지 사항 또는 (언어 plpgsql와) RAISE 다른 메시지를 보낼 수 있습니다 또는 당신은 (임시) 테이블을 작성하고 나중에이 문제를 해결하기 위해 그것에서 선택할 수 있습니다.

    다양한 방법으로 함수의 RETURNS 절 또는 OUT / INOUT 매개 변수와 반환과 반환 유형을 정의 할 수있는하지만 실제로는, 대신 (plpgsql) 함수를 만듭니다.

    당신이 기능을 저장하고 다른 연결 볼 수 원하지 않는 경우, 문서화되지 않은 있지만 잘 확립 된 기능이다 "일시적"기능을 고려 :

    손에서 문제를 들어 당신이 중 하나를 필요로하지 않는 것. 대신이 간단한 쿼리를 사용합니다 :

    SELECT row_number() OVER ()    AS running_month
         , extract('year'  FROM m) AS year
         , extract('month' FROM m) AS month
    FROM   generate_series(timestamp '2012-04-01'
                         , timestamp '2016-01-01'
                         , interval '1 month') m;
    

    DB <> 바이올린 여기

    왜?

  2. ==============================

    2.여기에 질문이 더 맞도록되어 있기 때문에, 질문에 진짜 대답해야 어윈이 조언하는 임시 테이블과 해결 방법에 대한 자세한 내용은 "개발 과정에서, 어떻게 빨리 선택과 코드 블록을 작성하고 결과를 볼 수 있습니다 "(하우투 빠르게"테이블 반환 함수 디버깅 / 핵 물질이이 실제 쿼리를 해결하는 것보다 처음부터 근본적인 질문을했다 "). 나는 내가 generate_series 부분 100 번 upvote에하고 싶은 말을해야하지만) 그것은 임시 테이블에 결과를 선택하는 것이 가능하다, 그리고, DO 블록 외부에서 임시 테이블에서 선택 이 같은 :

    여기에 질문이 더 맞도록되어 있기 때문에, 질문에 진짜 대답해야 어윈이 조언하는 임시 테이블과 해결 방법에 대한 자세한 내용은 "개발 과정에서, 어떻게 빨리 선택과 코드 블록을 작성하고 결과를 볼 수 있습니다 "(하우투 빠르게"테이블 반환 함수 디버깅 / 핵 물질이이 실제 쿼리를 해결하는 것보다 처음부터 근본적인 질문을했다 "). 나는 내가 generate_series 부분 100 번 upvote에하고 싶은 말을해야하지만) 그것은 임시 테이블에 결과를 선택하는 것이 가능하다, 그리고, DO 블록 외부에서 임시 테이블에서 선택 이 같은 :

    DO $$
        DECLARE r record;
        DECLARE i integer;
    
        DECLARE __iStartYear integer;
        DECLARE __iStartMonth integer;
    
    
        DECLARE __iEndYear integer;
        DECLARE __iEndMonth integer;
    
        DECLARE __mytext character varying(200);
    BEGIN
        i:= 5;
    
        -- Using Raise:
        -- http://www.java2s.com/Code/PostgreSQL/Postgre-SQL/UsingRAISENOTICE.htm
    
        --RAISE NOTICE  'test'
        --RAISE NOTICE  'test1' || 'test2';
    
    
        __mytext := 'Test message';
        --RAISE NOTICE __mytext;
        RAISE NOTICE '%', __mytext;
        RAISE NOTICE '%', 'arg1' || 'arg2';
        RAISE NOTICE '% %', 'arg1', 'arg2';
    
        --SQL Standard:  "CAST( value AS text )" [or varchar]
        --PostgreSQL short-hand:  "value::text"
        __mytext := 'Test ' || i::text;
        RAISE NOTICE '%', __mytext;
    
        __mytext := 'mynumber: ' || CAST(i as varchar(33)) || '%';
        RAISE NOTICE '%', __mytext;
    
        __iStartYear := 2012;
        __iStartMonth := 4;
    
         __iEndYear := 2016;
         __iEndMonth := 1;
    
         --PERFORM  'abc';
    
    
         --CREATE TEMP TABLE mytable AS SELECT * FROM orig_table;
    
         --DROP TABLE table_name CASCADE;
         --DROP TABLE IF EXISTS table_name CASCADE;
    
         --DROP TABLE IF EXISTS tbl;
         --CREATE TEMP TABLE tbl AS SELECT 1 as a,2 as b,3 as c;
    
    DROP TABLE IF EXISTS mytable;
    CREATE TEMP TABLE mytable AS
    
    
    WITH RECURSIVE CTE 
    AS
    (
    
            SELECT 
                 --__iStartYear AS TheStartYear 
                 __iStartMonth AS TheRunningMonth 
                ,__iStartYear AS TheYear  
                ,__iStartMonth AS TheMonth 
    
        UNION ALL 
    
            SELECT 
                 --CTE.TheStartYear AS TheStartYear 
                 --__iStartYear AS TheStartYear 
                 CTE.TheRunningMonth + 1 AS TheRunningMonth 
                --,CTE.TheStartYear + (CTE.TheRunningMonth / 12) AS TheYear 
                ,__iStartYear + (CTE.TheRunningMonth / 12) AS TheYear 
                ,(CTE.TheMonth + 1 -1) % 12 + 1 AS TheMonth
            FROM CTE 
            WHERE (1=1) 
    
            AND
            (
                CASE 
                    --WHEN (CTE.TheStartYear + (CTE.TheRunningMonth / 12) ) < __iEndYear 
                    WHEN (__iStartYear + (CTE.TheRunningMonth / 12) ) < __iEndYear 
                        THEN 1 
                    --WHEN (CTE.TheStartYear + (CTE.TheRunningMonth / 12) ) = __iEndYear 
                    WHEN (__iStartYear + (CTE.TheRunningMonth / 12) ) = __iEndYear 
                        THEN 
                            CASE 
                                WHEN ( (CTE.TheMonth + 1 -1) % 12 + 1 ) <= __iEndMonth 
                                    THEN 1 
                                ELSE 0 
                            END 
                    ELSE 0 
                END = 1 
            )
    
    )
    
    
    SELECT * FROM CTE; 
    
    
        -- SELECT  __iStartMonth AS TheRunningMonth; 
    
    
         --RAISE NOTICE  'The raise_test() function began.' + CAST( i AS text ) ;
        --FOR r IN SELECT table_schema, table_name FROM information_schema.tables WHERE table_type = 'VIEW' AND table_schema = 'public'
        --LOOP
          --  EXECUTE 'GRANT ALL ON ' || quote_ident(r.table_schema) || '.' || quote_ident(r.table_name) || ' TO webuser';
        --END LOOP;
    END$$;
    
    
    SELECT * FROM mytable;
    

    어떤 정말 빨리 BTW 다음과 같습니다 테이블 반환 기능 버전으로 쿼리를 설정하는 기본입니다 :

    -- SELECT * FROM tfu_V_RPT_MonthList(2012,1,2013,4);
    
    CREATE OR REPLACE FUNCTION tfu_V_RPT_MonthList
    ( 
         __iStartYear integer
        ,__iStartMonth integer
        ,__iEndYear integer
        ,__iEndMonth integer
    )
      RETURNS TABLE(
         TheRunningMonth integer
        ,TheYear integer
        ,TheMonth integer
    ) AS
    $BODY$
    DECLARE
    -- Declare vars here
    BEGIN
    RETURN QUERY 
    
    WITH RECURSIVE CTE 
    AS
    (
    
            SELECT 
                 --__iStartYear AS TheStartYear 
                 __iStartMonth AS TheRunningMonth 
                ,__iStartYear AS TheYear  
                ,__iStartMonth AS TheMonth 
    
        UNION ALL 
    
            SELECT 
                 --CTE.TheStartYear AS TheStartYear 
                 --__iStartYear AS TheStartYear 
                 CTE.TheRunningMonth + 1 AS TheRunningMonth 
                --,CTE.TheStartYear + (CTE.TheRunningMonth / 12) AS TheYear 
                ,__iStartYear + (CTE.TheRunningMonth / 12) AS TheYear 
                ,(CTE.TheMonth + 1 -1) % 12 + 1 AS TheMonth
            FROM CTE 
            WHERE (1=1) 
    
            AND
            (
                CASE 
                    --WHEN (CTE.TheStartYear + (CTE.TheRunningMonth / 12) ) < __iEndYear 
                    WHEN (__iStartYear + (CTE.TheRunningMonth / 12) ) < __iEndYear 
                        THEN 1 
                    --WHEN (CTE.TheStartYear + (CTE.TheRunningMonth / 12) ) = __iEndYear 
                    WHEN (__iStartYear + (CTE.TheRunningMonth / 12) ) = __iEndYear 
                        THEN 
                            CASE 
                                WHEN ( (CTE.TheMonth + 1 -1) % 12 + 1 ) <= __iEndMonth 
                                    THEN 1 
                                ELSE 0 
                            END 
                    ELSE 0 
                END = 1 
            )
    
    )
    
        SELECT * FROM CTE ;
    
    END;
    $BODY$
      LANGUAGE plpgsql VOLATILE
    
    
    --ALTER FUNCTION dbo.tfu_v_dms_desktop(character varying) OWNER TO postgres;
    

    BTW,이를 달성하기 위해 부풀게는 SQL-Server 코드를 보라 :

    SELECT 
         extract('year' FROM m) AS RPT_Year
        -- http://www.postgresql.org/docs/current/interactive/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE
        --,to_char(m, 'TMmon')
        --,to_char(m, 'TMmonth')
        ,to_char(m, 'Month') AS RPT_MonthName 
        ,m AS RPT_MonthStartDate
        ,m + INTERVAL '1 month' - INTERVAL '1 day' AS RPT_MonthEndDate 
    
    FROM 
    (
       SELECT 
            generate_series((2012::text || '-' || 4::text || '-01')::date, (2016::text || '-' || 1::text || '-01')::date, interval '1 month') AS m 
    ) AS g
    ;
    

    이로 바뀝니다 :

    DECLARE @in_iStartYear integer
    DECLARE @in_iStartMonth integer
    
    
    DECLARE @in_iEndYear integer
    DECLARE @in_iEndMonth integer
    
    SET @in_iStartYear = 2012
    SET @in_iStartMonth = 12
    
    
    SET @in_iEndYear = 2016
    SET @in_iEndMonth = 12
    
    
    
    DECLARE @strOriginalLanguage AS nvarchar(200) 
    DECLARE @dtStartDate AS datetime 
    DECLARE @dtEndDate AS datetime 
    
    
    SET @strOriginalLanguage = (SELECT @@LANGUAGE) 
    
    SET @dtStartDate = DATEADD(YEAR, @in_iStartYear - 1900, 0) 
    SET @dtStartDate = DATEADD(MONTH, @in_iStartMonth -1, @dtStartDate) 
    
    SET @dtEndDate = DATEADD(YEAR, @in_iEndYear - 1900, 0) 
    SET @dtEndDate = DATEADD(MONTH, @in_iEndMonth -1, @dtEndDate) 
    
    SET LANGUAGE 'us_english'
    
    
    ;WITH CTE_YearsMonthStartAndEnd 
    AS
    (
            SELECT
                 YEAR(@dtStartDate) AS RPT_Year 
                ,DATENAME(MONTH, @dtStartDate) AS RPT_MonthName 
                ,@dtStartDate AS RPT_MonthStartDate  
                ,DATEADD(DAY, -1, DATEADD(MONTH, 1, @dtStartDate)) AS RPT_MonthEndDate 
    
        UNION ALL
    
            SELECT 
                 YEAR(DATEADD(MONTH, 1, CTE_YearsMonthStartAndEnd.RPT_MonthStartDate)) AS RPT_Year 
                ,DATENAME(MONTH, DATEADD(MONTH, 1, CTE_YearsMonthStartAndEnd.RPT_MonthStartDate)) AS RPT_MonthName 
                ,DATEADD(MONTH, 1, CTE_YearsMonthStartAndEnd.RPT_MonthStartDate) AS RPT_MonthStartDate 
                ,DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(MONTH, 1, CTE_YearsMonthStartAndEnd.RPT_MonthStartDate)) ) AS RPT_MonthEndDate 
    
            FROM CTE_YearsMonthStartAndEnd 
            WHERE DATEADD(MONTH, 1, CTE_YearsMonthStartAndEnd.RPT_MonthStartDate) <= @dtEndDate 
    )
    
    SELECT 
         RPT_Year 
        ,RPT_MonthName 
        ,RPT_MonthStartDate 
        ,RPT_MonthEndDate 
    FROM CTE_YearsMonthStartAndEnd 
    

    (감사 어윈!))

  3. ==============================

    3.이것은 너무 오프 주제 (IMHO)이며, 도움이 될 수 있습니다 ...

    이것은 너무 오프 주제 (IMHO)이며, 도움이 될 수 있습니다 ...

    나는이 트랜잭션의 문들을 실행하고 (기록이 영향을 사용자 지정 오류 코드) 트랜잭션이 처리 된 방법 PHP 스크립트에 나타냅니다 일부 (아주 작은) 데이터를 반환하는 데 필요한 곳에 나는 최근에이 문제를 다 퉜다.

    인상주의 사항 및 RAISE [예외] 패러다임에 집착, 나는 그것이 최고의 반환되는주의 사항 / 예외 JSON 문자열을 반환 발견했다. 이 방법은 PHP 응용 프로그램이해야 할 것입니다 모두 사용 pg_last_notice () 또는 얻고 JSON 문자열을 디코딩하는 pg_last_error ()입니다.

    EG

    RAISE EXCEPTION '{"std_response":{"affected":%,"error":%}}', var_affected, var_error_id;
    

    또는

    RAISE NOTICE '{"std_response":{"affected":%,"error":%}}', var_affected, var_error_id;
    

    "std_response"라는 이름의 반환 JSON 객체가 실제로 스크립트의 모든 유형에 대한 표준 응답이기 때문에 하중이 래퍼 기능 때문에 쓰기 단위 테스트에 정말 쉽습니다을하게하고, SQL은 항상 할 수있는 "std_response"개체를 반환합니다 실행 그것의 값을 테스트했습니다.

    당신이 RAISE 메시지의 데이터 TINY 조각을 반환하는 경우 (-하지 않도록 한계가 무엇인지 내가 96,000 자까지 본 적이 있지만이 방법을 반환)이 패러다임에만 사용되어야한다. 당신이 큰 데이터 집합을 반환해야 할 경우, 당신은 테이블에 결과 집합을 저장하지만 적어도 당신은 여전히 ​​호출 된 SQL 속해 정확히 어떤 기록을 분리하는이 패러다임을 사용할 수 있어야합니다. 즉 UUID와 함께 테이블에 데이터를 배치 등등과 같은 공지의 UUID를 반환 :

    RAISE NOTICE '{"table_name":{"affected":%,"uuid":%}}', var_affected, var_uuid;
    

    이것에 대해 좋은 점은 여전히 ​​구조화 된 데이터를 선택 할 테이블 설명이기 때문에, 그것은 또한 응용 프로그램에서 단위 테스트와 함께 사용할 수 있다는 것입니다.

    (또는, 당신은 또한 그 방법은 당신이 I / O를 바로 저장하는 응용 프로그램을 결과를-디스크 세트를 처리하지 않아도, memcache에에 결과 세트를 저장하고 응용 프로그램 픽업에게 거기에서 데이터 집합을 가지고 PostgreSQL을 사용할 수 있습니다 ) 바로 다음 몇 가지 HTML을 생성 할 때 스크립트 완료를 버려야하는 데 사용할

  4. ==============================

    4.다음과 같은 방법을 사용할 수있는 DO 익명 코드 블록에서 레코드를 얻으려면 :

    다음과 같은 방법을 사용할 수있는 DO 익명 코드 블록에서 레코드를 얻으려면 :

    DO $$
    DECLARE
      _query text;
      _cursor CONSTANT refcursor := '_cursor';
    BEGIN
      _query := 'SELECT * FROM table_name';
      OPEN _cursor FOR EXECUTE _query;
    END
    $$;
    
    FETCH ALL FROM _cursor;
    

    주의

    더에 대한 커서. 기술 소스 여기 (러시아어).

  5. from https://stackoverflow.com/questions/14652477/how-to-perform-a-select-query-in-a-do-block by cc-by-sa and MIT license