É importante entender a natureza principal desses cinco diferentes tipos de dados/símbolos :
1. 'my_tbl'
Um literal de string de
unknown
tipo . Quando usado em SQL (embutido no código plpgsql ou não), ele é forçado a um tipo derivado do contexto . Se o tipo não puder ser determinado, uma conversão explícita pode ser necessária. Como:'my_tbl'::text
. 2. 'my_tbl'::text
O mesmo literal de string convertido para digite
text
. Ele pode conter o nome de uma tabela, mas na verdade é apenas texto. 3. 'my_tbl'::regclass
Um identificador de objeto (OID) para uma classe registrada . Ele é exibido e pode ser inserido como uma string representando um nome de objeto válido (
'my_tbl'
). A saída é automaticamente qualificada pelo esquema ('my_schema.my_tbl'
) e/ou aspas duplas ('"mY_TbL"'
) se for ambíguo ou ilegal de outra forma. Pode ser uma tabela normal , sequência , ver , visualização materializada , tipo composto etc. Detalhes nesta resposta relacionada:4. my_tbl_var my_tbl
(abreviação de my_tbl_var my_tbl%ROWTYPE
)
No
DECLARE
seção de um bloco de código plpgsql que é uma declaração de variável com um conhecido tipo de linha
(também conhecido como tipo composto). O tipo deve ser registrado na tabela do sistema pg_class
(o mesmo que com uma regclass
variável). Não é o OID do objeto referenciado, mas seu tipo de linha real. my_tbl_var
e my_tbl
são ambos identificadores aqui e não pode ser parametrizado. Você também pode converter qualquer linha ou registro diretamente:(123, 'foo')::my_tbl
5. my_tbl_var record
No
DECLARE
seção de um bloco de código plpgsql que é a declaração de um anônimo registro
. Basicamente, um espaço reservado para um tipo de linha ainda desconhecido / com estrutura ainda indefinida. Pode ser usado na maioria dos locais em que um tipo de linha pode ser usado. Mas você não pode acessar campos dele antes que a variável de registro seja atribuída. Você estava confundindo 1. , 3. e 4. e resolveu usando 5. em vez disso.
Mas há mais coisas erradas aqui:
-
Você está selecionando uma tabela inteira, mas uma variável de linha (registro) pode conter apenas uma linha por vez. Portanto, apenas o primeiro é atribuído e retornado. Enquanto não houverORDER BY
cláusula, o resultado é arbitrário e pode mudar a qualquer momento. Armadilha do mal.
-
Como agora você está usando umrecord
type, você precisa ter certeza de que ele foi atribuído antes de executar testes em seus campos, ou você obterá exceções para tabelas vazias. No seu caso, a verificaçãorecord_var IS NULL
quase faz o mesmo trabalho. Mas há um caso de canto para linhas com NULL em todos os campos:entãorecord_var IS NULL
avalia como verdadeiro. Ainda mais complicado para o testeIS NOT NULL
. Detalhes aqui:
Adicionei uma demonstração ao fiddle SQL abaixo de.
-
A função retorna um único escalar (boolean
) valor. Usar:
RETURN false;
Ao invés de:
RETURN QUERY SELECT false;
Função
CREATE FUNCTION check_valid(_tbl regclass)
RETURNS bool AS
$func$
DECLARE
r record;
_row_ct int;
BEGIN
EXECUTE '
SELECT is_valid, hit_count, hit_limit
FROM ' || _tbl || '
ORDER <whatever>
LIMIT 1' -- replace <whatever> with your sort criteria
INTO r; -- only needed columns
GET DIAGNOSTICS _row_ct = ROW_COUNT;
IF _row_ct = 0 THEN -- necessary, because r may not be assigned
RETURN false;
ELSIF NOT r.is_valid OR r.hit_count > r.hit_limit THEN
RETURN false;
END IF;
RETURN true;
END
$func$ LANGUAGE plpgsql;
SQL Fiddle (com duas variantes da função e uma demonstração para a linha IS NULL).
Pontos principais
-
UseGET DIAGNOSTICS
para descobrir se alguma linha foi encontrada em uma instrução dinâmica comEXECUTE
.
-
OIF
expressão pode ser simplificada.
-
O parâmetro é do tiporegclass
, não apenas um nome de tabela. Eu não usaria o nome enganoso "tablename" para esse parâmetro. Isso só aumenta sua confusão inicial. Chamando de_tbl
em vez de.
Se você também quiser retornar um conjunto de tipo de linha variável: