AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 24518
Accepted
dezso
dezso
Asked: 2012-09-20 00:32:46 +0800 CST2012-09-20 00:32:46 +0800 CST 2012-09-20 00:32:46 +0800 CST

Como parar condicionalmente um script psql (com base em um valor de variável)?

  • 772

Vamos considerar o seguinte exemplo (do início de um script psql):

\c :db_to_run_on

TRUNCATE the_most_important_table;
-- tried to avoid similarities to anything that exists out there

Agora, se for executado pelo comando

psql [connection details] -v db_to_run_on=\'dev_database\'

então ele simplesmente roda e o usuário fica feliz. Mas e se ele decidir especificar -v db_to_run_on=production_database? (Vamos supor que isso possa acontecer, assim como as pessoas executam rm -rf / # don't try this at home!!!ocasionalmente.) Espero que haja um novo backup dessa tabela ...

Então surge a pergunta: como verificar as variáveis ​​passadas para um script e interromper o processamento posterior com base em seu valor?

postgresql psql
  • 6 6 respostas
  • 17461 Views

6 respostas

  • Voted
  1. dezso
    2012-09-26T00:00:22+08:002012-09-26T00:00:22+08:00

    Existe uma opção em psqlque para de executar comandos em caso de erro, é ON_ERROR_STOP. Se pudéssemos gerar um erro de alguma forma, isso faria o que queremos.

    O problema é que temos que testar a variável e produzir um erro de alguma forma. Como não se pode usar estruturas de controle em psql(porque não existem) *, minha única ideia era usar SQL para teste. Bem, produzir um erro condicionalmente é algo em que pl/pgsqlé muito bom, então escrevi uma função que geraria um erro. Agora posso chamar essa função a partir de uma CASEestrutura simples. Um exemplo simples:

    -- let's assume for clarity that there is no function with this name in the database
    CREATE OR REPLACE FUNCTION error_generator()
    RETURNS boolean AS
    $body$
    BEGIN
        RAISE 'Meaningful error message here';
        RETURN FALSE; -- just for aesthetical purposes
    END;
    $body$
    LANGUAGE plpgsql;
    
    \set ON_ERROR_STOP on
    
    BEGIN;
    
    -- test for the variable value
    -- notice that if :var is not set, it fails as well (with a syntax error)
    SELECT CASE WHEN 1 = :var THEN error_generator() ELSE TRUE END;
    
    INSERT INTO test_table (integer_value, text_value)
    VALUES (:var, 'something');
    
    COMMIT;
    

    *: Você pode usar qualquer comando shell depois \!e condicionais do shell, mas como \!abre um novo shell, executar qualquer coisa lá não tem nenhum efeito para o script psql atual.

    • 17
  2. Best Answer
    Evan Carroll
    2017-04-07T13:20:50+08:002017-04-07T13:20:50+08:00

    PostgreSQL 10

    PostgreSQL 10 traz condicionais para psql. Isso não é mais um problema.

    \if :db_to_run_on = 'dev_database'
      TRUNCATE the_most_important_table;
    \endif
    

    Eu acho que você também poderia usar DO..

    \if :db_to_run_on != 'dev_database'
    do $$
      BEGIN
        RAISE 'Meaningful error message here';
      END;
    $$ LANGUAGE plpgsql;
    \endif
    
    • 8
  3. Steve Bennett
    2018-08-09T18:41:28+08:002018-08-09T18:41:28+08:00

    Uma versão mais concisa da resposta de dezso:

    CREATE OR REPLACE FUNCTION pg_temp.err(msg varchar) RETURNS boolean     
    AS $$ BEGIN RAISE '%',msg; END; $$ LANGUAGE plpgsql;
    

    Você pode então chamar isso como:

    \set ON_ERROR_STOP on
    
    SELECT CASE WHEN (
      SELECT COUNT(*) FROM mytable
    ) > 0 THEN pg_temp.err('Already loaded') END;
    
    • 2
  4. François Beausoleil
    2012-09-20T17:03:36+08:002012-09-20T17:03:36+08:00

    O que descobri que funciona muito bem para mim é usar uma linguagem de script para gerar um arquivo SQL que eu canalizo para o psql, algo assim:

    #!/usr/bin/env ruby
    
    raise "Not a good database name: #{ARGV.first.inspect}" unless ARGV.first =~ /^(dev|test)/
    
    puts "\\timing off"
    puts "set client_min_messages='warning';"
    puts
    puts "TRUNCATE the_most_important_table;"
    puts "-- more commands"
    

    Então, eu chamo isso de um script de driver:

    #!/bin/bash
    /usr/bin/ruby generator ${1} | /usr/bin/psql --dbname=${1} --file=- --single-transaction
    

    Meu script de driver geralmente é um arquivo Rake, mas você entendeu.

    • 1
  5. tbussmann
    2022-01-18T13:24:48+08:002022-01-18T13:24:48+08:00

    Para sair psqlde um script, você pode simplesmente usar o \quitcomando meta ou gerar um erro enquanto estiver ON_ERROR_STOPativo. As diferenças são:

    • \quitfará uma saída limpa com status 0ou encerrará apenas o script em execução se estiver usando scripts aninhados ou\i
    • produzir um erro ao ON_ERROR_STOPser ativado sairá com status 3e se propagará para o script de nível superior no caso de scripts aninhados.

    Uma alternativa mais fácil para gerar um erro e executar RAISEa partir de uma função ou bloco de código anônimo é apenas um comando SQL inválido como: INVALID;.

    Para exibir a mensagem de erro, você pode usar o \warnmeta-comando que a envia para stderr(começando na página 13) ou simplesmente \echopara stdout.

    Combinado com \if(começando na página 10), minha tentativa para o problema do OP seria:

    SELECT :'db_to_run_on' = 'production_database' AS forbidden \gset
    \if :forbidden
        \warn 'You better not do this!'
        \set ON_ERROR_STOP on
        INVALID COMMAND;
    \endif
    \unset forbidden
    
    \c :db_to_run_on
    TRUNCATE the_most_important_table;
    

    Infelizmente, não conheço uma maneira de suprimir a saída de 'erro de sintaxe' gerada pelo comando inválido. Portanto, dependendo do seu caso de uso, combinar \warn 'You better not do this!'e \quitou \set ON_ERROR_STOP one DO $$BEGIN RAISE 'You better not do this!'; END$$ LANGUAGE plpgsql;pode ser mais adequado.

    • 0
  6. Qwertie
    2022-06-22T09:25:52+08:002022-06-22T09:25:52+08:00

    Em um script de consulta (que eu acho que é de alguma forma diferente de um script psql), \iffoi considerado um erro de sintaxe, mas um código como este funcionou para mim:

    DO $$ BEGIN
        IF problematic_value = 'undesired thing' THEN
            RAISE EXCEPTION 'Aborting: % is no good', problematic_value;
        END IF;
    END $$;
    

    Testado no PostgreSQL 13.2. DOO bloco externo não é necessário dentro de um procedimento armazenado.

    • 0

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve