Eu tenho um aplicativo que (como parte de sua lógica) corta strings e substitui strings vazias por NULL antes da inserção no banco de dados. Acho que uma maneira de garantir que isso seja aplicado seria escrever um CHECK em todas as tabelas que possuem uma coluna VARCHAR
, (ou similar).TEXT
Supondo que alguém não possa ou não queira fazer isso, existe uma maneira de escrever uma consulta SQL simples e genérica (obtendo nomes de tabelas e colunas dos metadados do banco de dados) que verificaria se alguma coluna de texto no banco de dados contém strings vazias ?
A melhor maneira de fazer isso é com uma
CHECK
restrição, como você observou, possivelmente por meio de umDOMAIN
, por exemploem seguida,
ALTER
colunas existentes para usar o domínio.Se isso não for possível, você precisará consultar
INFORMATION_SCHEMA
para localizar todas as colunas do tipo de destino em todas as tabelas e, para cada coluna, gerar dinamicamente uma consulta para verificação. Você pode usar PL/PgSQL e aEXECUTE
instrução para isso; há muitos exemplos de seu uso dessa maneira em outro lugar no Stack Overflow.Você não pode escrever uma única consulta para fazer o que deseja. Simplesmente não vai funcionar. Você terá que usar a geração de consulta de
information_schema
.Função para uma única tabela
Retorna todas as colunas de tipo de caractere da tabela fornecida com uma contagem de valores vazios (
''
) e se eles estão definidosNOT NULL
.Ligar:
Retorna:
Funciona para Postgres 9.1 ou posterior.
Os nomes das tabelas de saída são automaticamente qualificados pelo esquema, se necessário, de acordo com o
search_path
.Os nomes da tabela de saída e os nomes das colunas são escapados automaticamente, se necessário.
empty_ct
é a contagem de linhas onde o valor da coluna é a string vazianot_null
informa se a coluna está definidaNOT NULL
(portanto, você não pode converter possíveis strings vazias em NULL!)O nome da tabela de entrada pode opcionalmente ser qualificado pelo esquema, caso contrário, o padrão é o atual
search_path
.Sua função precisa de privilégios para realmente ler a tabela fornecida.
A função é altamente otimizada e executa apenas uma única varredura na tabela fornecida para verificar todas as colunas relevantes.
Deve ser seguro contra injeção de SQL.
Usando paralelo
unnest()
para simplificar um pouco o código complexo:Você estará interessado nesta resposta relacionada no SO para realmente substituir strings vazias - com mais explicações :
Corresponde também a sequências de apenas caracteres de espaço
Como você comentou ,
trim(s.col, ' ') = ''
faz o trabalho muito bem. Mas aqui está um atalho:Como?
char
é um alias paracharacter(1)
, o tipo de preenchimento em branco raramente útil. Os valores são preenchidos com caracteres de espaço à direita até o especificador de comprimento (que1
, neste caso, é irrelevante). Espaços à direita são efetivamente insignificantes para este tipo. Então' '
é o mesmo que''
ou' '
. Voilá. E sim, é mais rápido também, testei.Para encontrar strings com apenas caracteres de espaço também (não outros espaços em branco!), adicione a conversão a estas linhas acima:
Função wrapper para relatar um esquema inteiro
Ligar:
Retorna:
db<>fiddle aqui
Old sqlfiddle