복붙노트

[SQL] PostgreSQL의 쿼리에서 명명 된 상수를 정의 할 수있는 방법이 있습니까?

SQL

PostgreSQL의 쿼리에서 명명 된 상수를 정의 할 수있는 방법이 있습니까?

PostgreSQL의 쿼리에서 명명 된 상수를 정의 할 수있는 방법이 있습니까? 예를 들면 :

MY_ID = 5;
SELECT * FROM users WHERE id = MY_ID;

해결법

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

    1.이 질문은 전에 물어되었습니다 (어떻게 PostgreSQL의에서 스크립트 변수를 사용합니까?). 그러나, 나는 가끔 쿼리에 사용하는 트릭이있다 :

    이 질문은 전에 물어되었습니다 (어떻게 PostgreSQL의에서 스크립트 변수를 사용합니까?). 그러나, 나는 가끔 쿼리에 사용하는 트릭이있다 :

    with const as (
        select 1 as val
    )
    select . . .
    from const cross join
         <more tables>
    

    즉, 내가 CTE는 상수가 정의되어 CONST라고 정의한다. 나는 그 십자가 내 쿼리, 모든 수준에서 여러 번에이 가입하실 수 있습니다. 나는 많은 서브 쿼리를 통해 핸들 날짜 상수이 특히 내가 날짜를 처리하고있을 때 유용하고, 필요를 발견했다.

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

    2.PostgreSQL을 더 건설하지-에있다 MySQL의 또는 Oracle과 같은 (전역) 변수를 정의하는 방법입니다. ( "사용자 옵션"을 사용하여 제한된 해결 방법이 있습니다). 정확히 다른 방법이하려는 작업에 따라 :

    PostgreSQL을 더 건설하지-에있다 MySQL의 또는 Oracle과 같은 (전역) 변수를 정의하는 방법입니다. ( "사용자 옵션"을 사용하여 제한된 해결 방법이 있습니다). 정확히 다른 방법이하려는 작업에 따라 :

    이미 제공 @Gordon 같은 CTE에서 쿼리의 상단에 값을 제공 할 수 있습니다.

    당신은 그것에 대한 간단한 불변의 함수를 만들 수 있습니다 :

    CREATE FUNCTION public.f_myid()
      RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
    'SELECT 5';
    

    (병렬 안전 설정은 포스트 그레스 9.6 이상에 적용됩니다.)

    이것은 즉, 현재 사용자에게 표시되며, 각 search_path의 인 스키마에 거주한다. 기본적으로 스키마 대중처럼. 보안이 문제가되는 경우, 그것은 당신의 전화에 그것을 자격을 스키마 search_path의 또는에서 첫 번째 스키마의 확인 :

    SELECT public.f_myid();
    

    데이터베이스의 모든 사용자가 볼 수 (즉,이 액세스 스키마 대중에게 사용할 수 있습니다).

    CREATE TEMP TABLE val (val_id int PRIMARY KEY, val text);
    INSERT INTO val(val_id, val) VALUES
      (  1, 'foo')
    , (  2, 'bar')
    , (317, 'baz');
    
    CREATE FUNCTION f_val(_id int)
      RETURNS text LANGUAGE sql STABLE PARALLEL RESTRICTED AS
    'SELECT val FROM val WHERE val_id = $1';
    
    SELECT f_val(2);  -- returns 'baz'
    

    임시 테이블이 기능이 지속되는 동안 세션이 끝날 때 삭제하더라도 - plpgsql 검사 작성의 테이블의 존재 때문에, 당신은 당신이 함수를 작성하기 전에 (임시) 테이블 발을 작성해야합니다. 기본 테이블이 호출시에 발견되지 않는 경우,이 함수는 예외를 발생시킬 것이다.

    임시 개체에 대한 현재 스키마는 기본적 당 search_path의 가장 우선적으로 제공 - 달리 명시 적으로 지시하지 않은 경우. 당신은 search_path의에서 임시 스키마를 제외 할 수는 없지만 먼저 다른 스키마를 넣을 수 있습니다. (필요한 권한이있는) 밤의 사악한 생물은 search_path의 어설프게 전면에 같은 이름의 또 다른 목적을 넣을 수 있습니다

    CREATE TABLE myschema.val (val_id int PRIMARY KEY, val text);
    INSERT INTO val(val_id, val) VALUES (2, 'wrong');
    
    SET search_path = myschema, pg_temp;
    
    SELECT f_val(2);  -- returns 'wrong'
    

    전용 권한이있는 사용자는 전역 설정을 변경할 수 있기 때문에 그것은, 위협의 대부분이 아니다. 다른 사용자는 자신의 세션을 위해 그것을 할 수 있습니다. SECURITY DEFINER과 기능을 만드는 방법에 대한 설명서의 관련 장을보십시오.

    하드 유선 스키마는 일반적으로 간단하고 빠른 :

    CREATE FUNCTION f_val(_id int)
      RETURNS text LANGUAGE sql STABLE PARALLEL RESTRICTED AS
    'SELECT val FROM pg_temp.val WHERE val_id = $1';

    더 많은 옵션과 관련 답변 :

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

    3.감각적 인 고든과 어윈은 이미 언급 한 옵션 (임시 테이블 등 일정 리턴하는 함수, 열팽창 계수) 외에도 (AB) global-, 세션 - 트랜잭션 수준의 변수를 생성하기 위해 PostgreSQL의 GUC 메커니즘을 사용할 수 있습니다.

    감각적 인 고든과 어윈은 이미 언급 한 옵션 (임시 테이블 등 일정 리턴하는 함수, 열팽창 계수) 외에도 (AB) global-, 세션 - 트랜잭션 수준의 변수를 생성하기 위해 PostgreSQL의 GUC 메커니즘을 사용할 수 있습니다.

    자세히 접근 방식을 보여줍니다이 이전 게시물을 참조하십시오.

    나는 일반적인 사용이 권장되지 않습니다,하지만 포스터 트리거 및 기능에 대한 응용 프로그램 수준의 사용자 이름을 제공 할 수있는 방법을 원 링크 된 질문에서 언급 한 같은 좁은 경우에 유용 할 수 있습니다.

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

    4.내가 가장 잘 할 수있는 가능한 방법의 혼합물을 발견했습니다 :

    내가 가장 잘 할 수있는 가능한 방법의 혼합물을 발견했습니다 :

    CREATE TABLE vars (
      id INT NOT NULL PRIMARY KEY DEFAULT 1,
      zipcode INT NOT NULL DEFAULT 90210,
      -- etc..
      CHECK (id = 1)
    );
    
    CREATE FUNCTION generate_var_getter()
    RETURNS VOID AS $$
    DECLARE
      var_name TEXT;
      var_value TEXT;
      new_rows TEXT[];
      new_sql TEXT;
    BEGIN
      FOR var_name IN (
        SELECT columns.column_name
        FROM information_schema.columns
        WHERE columns.table_schema = 'public'
          AND columns.table_name = 'vars'
        ORDER BY columns.ordinal_position ASC
      ) LOOP
        EXECUTE
          FORMAT('SELECT %I FROM vars LIMIT 1', var_name)
          INTO var_value;
    
        new_rows := ARRAY_APPEND(
          new_rows,
          FORMAT('(''%s'', %s)', var_name, var_value)
        );
      END LOOP;
    
      new_sql := FORMAT($sql$
        CREATE OR REPLACE FUNCTION var_get(key_in TEXT)
        RETURNS TEXT AS $config$
        DECLARE
          result NUMERIC;
        BEGIN
          result := (
            SELECT value FROM (VALUES %s)
            AS vars_tmp (key, value)
            WHERE key = key_in
          );
          RETURN result;
        END;
        $config$ LANGUAGE plpgsql IMMUTABLE;
      $sql$, ARRAY_TO_STRING(new_rows, ','));
    
      EXECUTE new_sql;
      RETURN;
    END;
    $$ LANGUAGE plpgsql;
    
    CREATE FUNCTION vars_regenerate_update()
    RETURNS TRIGGER AS $$
    BEGIN
      PERFORM generate_var_getter();
      RETURN NULL;
    END;
    $$ LANGUAGE plpgsql;
    
    CREATE TRIGGER trigger_vars_regenerate_change
      AFTER INSERT OR UPDATE ON vars
      EXECUTE FUNCTION vars_regenerate_update();
    

    지금 당신은 쉽게 테이블에 변수를 유지할 수 있습니다, 또한 그들에게 타오르는 빠른 불변 액세스 할 수 있습니다. 두 세계의 최고:

    INSERT INTO vars DEFAULT VALUES;
    -- INSERT 0 1
    
    SELECT var_get('zipcode')::INT; 
    -- 90210
    
    UPDATE vars SET zipcode = 84111;
    -- UPDATE 1
    
    SELECT var_get('zipcode')::INT;
    -- 84111
    
  5. ==============================

    5.나는이 솔루션을 발견했습니다 :

    나는이 솔루션을 발견했습니다 :

    with vars as (
        SELECT * FROM (values(5)) as t(MY_ID)
    )
    SELECT * FROM users WHERE id = (SELECT MY_ID FROM vars)
    
  6. from https://stackoverflow.com/questions/13316773/is-there-a-way-to-define-a-named-constant-in-a-postgresql-query by cc-by-sa and MIT license