Check if database exists in PostgreSQL using shell

前端 未结 14 1388
南笙
南笙 2020-12-04 06:13

I was wondering if anyone would be able to tell me about whether it is possible to use shell to check if a PostgreSQL database exists?

I am making a shell script and

相关标签:
14条回答
  • 2020-12-04 07:04

    I'm new to postgresql, but the following command is what I used to check if a database exists

    if psql ${DB_NAME} -c '\q' 2>&1; then
       echo "database ${DB_NAME} exists"
    fi
    
    0 讨论(0)
  • 2020-12-04 07:04
    #!/bin/sh
    DB_NAME=hahahahahahaha
    psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
    RESULT=$?
    echo DATABASE=${DB_NAME} RESULT=${RESULT}
    #
    
    0 讨论(0)
  • 2020-12-04 07:05

    Trigger divide by zero if it doesn't exist then check return code like this:

    sql="SELECT 1/count(*) FROM pg_database WHERE datname='db_name'";
    error=$(psql -h host -U user -c "$sql" postgres);
    if $error
    then
      echo "doesn't exist";
    else
      echo "exists";
    fi
    
    0 讨论(0)
  • 2020-12-04 07:08

    The other solutions (which are fantastic) miss the fact that psql can wait a minute or more before timing out if it can't connect to a host. So, I like this solution, which sets the timeout to 3 seconds:

    PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""
    

    This is for connecting to a development database on the official postgres Alpine Docker image.

    Separately, if you're using Rails and want to setup a database if it doesn't already exist (as when launching a Docker container), this works well, as migrations are idempotent:

    bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
    
    0 讨论(0)
  • 2020-12-04 07:15

    I use the following modification of Arturo's solution:

    psql -lqt | cut -d \| -f 1 | grep -qw <db_name>


    What it does

    psql -l outputs something like the following:

                                            List of databases
         Name  |   Owner   | Encoding |  Collate   |   Ctype    |   Access privileges   
    -----------+-----------+----------+------------+------------+-----------------------
     my_db     | my_user   | UTF8     | en_US.UTF8 | en_US.UTF8 | 
     postgres  | postgres  | LATIN1   | en_US      | en_US      | 
     template0 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
               |           |          |            |            | postgres=CTc/postgres
     template1 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
               |           |          |            |            | postgres=CTc/postgres
    (4 rows)
    

    Using the naive approach means that searching for a database called "List, "Access" or "rows" will succeed. So we pipe this output through a bunch of built-in command line tools to only search in the first column.


    The -t flag removes headers and footers:

     my_db     | my_user   | UTF8     | en_US.UTF8 | en_US.UTF8 | 
     postgres  | postgres  | LATIN1   | en_US      | en_US      | 
     template0 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
               |           |          |            |            | postgres=CTc/postgres
     template1 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
               |           |          |            |            | postgres=CTc/postgres
    

    The next bit, cut -d \| -f 1 splits the output by the vertical pipe | character (escaped from the shell with a backslash), and selects field 1. This leaves:

     my_db             
     postgres          
     template0         
    
     template1         
    

    grep -w matches whole words, and so won't match if you are searching for temp in this scenario. The -q option suppresses any output written to the screen, so if you want to run this interactively at a command prompt you may with to exclude the -q so something gets displayed immediately.

    Note that grep -w matches alphanumeric, digits and the underscore, which is exactly the set of characters allowed in unquoted database names in postgresql (hyphens are not legal in unquoted identifiers). If you are using other characters, grep -w won't work for you.


    The exit status of this whole pipeline will be 0 (success) if the database exists or 1 (failure) if it doesn't. Your shell will set the special variable $? to the exit status of the last command. You can also test the status directly in a conditional:

    if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
        # database exists
        # $? is 0
    else
        # ruh-roh
        # $? is 1
    fi
    
    0 讨论(0)
  • 2020-12-04 07:16
    postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l
    

    This will return 1 if the database specified exists or 0 otherwise.

    Also, if you try to create a database that already exists, postgresql will return an error message like this:

    postgres@desktop:~$ createdb template1
    createdb: database creation failed: ERROR:  database "template1" already exists
    
    0 讨论(0)
提交回复
热议问题