2013-07-04 2 views
1

:PostgreSQL의 기능 오류 : 열 이름이 존재하지 않는 내가 값이 특정 테이블의 특정 행에 나타납니다 있는지 확인하는 기능 구현했습니다

CREATE FUNCTION check_if_if_exist(id INTEGER, table_name character(50), table_column character(20)) RETURNS BOOLEAN AS $$ 

DECLARE res BOOLEAN; 

BEGIN 
    SELECT table_column INTO res 
    FROM table_name 
    WHERE table_column = id; 

    RETURN res; 
END; 

$$ LANGUAGE plpgsql 

내가 만든 간단한 테스트 테이블을 채우기 한을 이 기능 시도에 대해 :

CREATE TABLE tab(f INTEGER); 

을하고 난 기능과 ​​같은

SELECT check_if_exist(10, tab, f); 

를 호출하지만 난이 오류가 발생합니다 :

ERROR: column "prova" does not exist 
LINE 1: SELECT check_if_exist(10, tab, f); 
          ^


********** Error ********** 

ERROR: column "tab" does not exist 
SQL state: 42703 
Character: 27 

왜?

+0

"존재하지 않을 경우 삽입"또는 "업데이트, 존재하지 않는다면 삽입"형식으로이 작업을 수행하려는 경우 지금 중단하고 PostgreSQL의 upsert에 대해 읽어보십시오. 그것이 당신이하고있는 것과 다르다면 편집하고 실제 목표가 무엇인지 설명하십시오.이를 수행하는 더 좋은 방법이없는 곳에서 사용하는 것과 같은 기능을 상상하기 란 어렵습니다. –

답변

2

코드는 일할 기회가 없다 - http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
을하지만 우선 - - PLPGSQL에서 다른 테이블을 처리 할 때 당신이 그렇게 EXECUTE이 필요하며, 동적 쿼리를 이용해야하는 대신 http://www.postgresql.org/docs/current/static/functions-subquery.html#AEN15284 - 나쁜 아무것도 EXISTS을 PostgreSQL의를 사용하여이 없다 자신 만의 배터리를 만드는 것보다 성능이 나빠질 것입니다 ...
잘하면이 도움이 될 것입니다. 행운을 빕니다.

2

Elmo 응답 외에도 유형에주의해야합니다. 당신은 가지고있다 : SQL 파서 따옴표없이 tab 처리하는 방법을 모르는

ERROR: column "tab" does not exist 

때문이다. 귀하의 질의해야합니다 같은 : 엘모 당신이 tab 당신이 가지고 것이다 오류를 인용 그렇게하더라도, 동적 쿼리를 사용하여 대답으로

SELECT check_if_exist(10, 'tab', 'f'); 

:

ERROR: relation "table_name" does not exist 

그래서 당신이 EXECUTE을 사용할 수 있습니다, 예 :

CREATE OR REPLACE FUNCTION check_if_exist(id INTEGER, table_name varchar, table_column varchar) RETURNS BOOLEAN AS $$ 
    DECLARE 
     sql varchar; 
     cnt int; 
    BEGIN 
     sql := 'SELECT count(*) FROM ' || quote_ident(table_name) || ' WHERE ' || quote_ident(table_column) || '=$1'; 
     RAISE NOTICE 'sql %', sql; 
     EXECUTE sql USING id INTO cnt; 
     RETURN cnt > 0; 
    END; 
$$ LANGUAGE plpgsql 

함수 인수에 character(N) 대신 VARCHAR을 사용하고대신 CREATE OR REPLACE FUNCTION ...을 사용할 수도 있습니다은 디버깅에 매우 편리합니다.

+4

'EXECUTE'을 직접 문자열 연결로 표시하지 마십시오. 함수를 SQL 삽입을위한 벡터로 만듭니다. 위의 예는 'EXECUTE format'('SELECT count (*) FROM % I WHERE % I = $ 1', table_name, table_column) USING ID INTO cnt;'또는 'format'이없는 오래된 PostgreSQL 버전의 경우 테이블을 래핑해야합니다 'quote_ident' 호출에서 열 이름을 사용합니다. 대답은 –

+0

+1입니다. 그러나 @CraigRinger는 그의 걱정거리가 옳았습니다. +1도 마찬가지입니다. OP를 동적 쿼리로 만들고 SQL 인젝션을 방지하는 방법을 보여주는 것이 좋지만,이 정확한 함수를 작성하는 것이 휠을 재발 명한다고합니다. – ElmoVanKielmo

+0

감사합니다. 방금 답변을 수정했습니다. 이 함수는'select exists (select * from my_table where my_column = my_value)'를 사용할 때 매우 유용하지 않습니다. –