Câu trả lời:
Tôi sử dụng sửa đổi sau đây của giải pháp của Arturo:
psql -lqt | cut -d \| -f 1 | grep -qw <db_name>
psql -l
xuất ra một cái gì đó như sau:
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)
Sử dụng cách tiếp cận ngây thơ có nghĩa là tìm kiếm cơ sở dữ liệu có tên "Danh sách", "Truy cập" hoặc "hàng" sẽ thành công. Vì vậy, chúng tôi dẫn đầu ra này thông qua một loạt các công cụ dòng lệnh tích hợp để chỉ tìm kiếm trong cột đầu tiên.
Các -t
cờ loại bỏ tiêu đề và chân trang:
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
Bit tiếp theo, cut -d \| -f 1
phân tách đầu ra theo |
ký tự ống đứng (thoát khỏi vỏ bằng dấu gạch chéo ngược) và chọn trường 1. Điều này để lại:
my_db
postgres
template0
template1
grep -w
khớp toàn bộ từ và vì vậy sẽ không khớp nếu bạn đang tìm kiếm temp
trong kịch bản này. Các -q
tùy chọn ngăn chặn bất kỳ đầu ra bằng văn bản cho màn hình, vì vậy nếu bạn muốn chạy này một cách tương tác tại dấu nhắc lệnh bạn có thể có để loại trừ-q
một cái gì đó để được hiển thị ngay lập tức.
Lưu ý rằng grep -w
khớp với chữ và số, chữ số và dấu gạch dưới, chính xác là tập hợp các ký tự được phép trong tên cơ sở dữ liệu không được trích dẫn trong postgresql (dấu gạch nối không hợp pháp trong số nhận dạng không được trích dẫn). Nếu bạn đang sử dụng các nhân vật khác, grep -w
sẽ không làm việc cho bạn.
Trạng thái thoát của toàn bộ đường ống này sẽ là 0
(thành công) nếu cơ sở dữ liệu tồn tại hoặc 1
(thất bại) nếu không. Shell của bạn sẽ đặt biến đặc biệt $?
thành trạng thái thoát của lệnh cuối cùng. Bạn cũng có thể kiểm tra trạng thái trực tiếp trong một điều kiện:
if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
# database exists
# $? is 0
else
# ruh-roh
# $? is 1
fi
wc
hoàn toàn. Xem bản sửa đổi của tôi. (Nếu bạn muốn đảo ngược trạng thái thoát, Bash hỗ trợ toán tử bang ! psql ...
:)
wc
lệnh, tôi sẽ sử dụng grep -qw <term>
. Điều này sẽ khiến vỏ trở lại 0
nếu có một trận đấu và 1
nếu không. Sau đó, $?
sẽ chứa giá trị trả về và bạn có thể sử dụng giá trị đó để quyết định làm gì tiếp theo. Vì vậy, tôi khuyên bạn không nên sử dụng wc
trong trường hợp này. grep
sẽ làm những gì bạn cần.
Mã shell sau đây dường như hoạt động với tôi:
if [ "$( psql -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" )" = '1' ]
then
echo "Database already exists"
else
echo "Database does not exist"
fi
psql -U user -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" template1
if [[ $(...) == 1* ]]
postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l
Điều này sẽ trả về 1 nếu cơ sở dữ liệu được chỉ định tồn tại hoặc 0 nếu không.
Ngoài ra, nếu bạn cố gắng tạo một cơ sở dữ liệu đã tồn tại, postgresql sẽ trả về một thông báo lỗi như thế này:
postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR: database "template1" already exists
exact_dbname_test
sẽ tồn tại? Cách duy nhất để thử nghiệm là cố gắng kết nối với nó.
psql -l | grep doesnt_matter_what_you_grep | wc -l && echo "true"
vspsql -l | grep it_does_matter_here && echo "only true if grep returns anything"
psql -l | grep '^ exact_dbname\b'
, nó đặt mã thoát nếu không tìm thấy.
Tôi mới sử dụng postgresql, nhưng lệnh sau đây là những gì tôi đã sử dụng để kiểm tra xem cơ sở dữ liệu có tồn tại không
if psql ${DB_NAME} -c '\q' 2>&1; then
echo "database ${DB_NAME} exists"
fi
psql ${DB_NAME} -c ''
.
Bạn có thể tạo cơ sở dữ liệu, nếu nó chưa tồn tại, sử dụng phương pháp này:
if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi
Tôi đang kết hợp các câu trả lời khác với dạng tương thích ngắn gọn và POSIX:
psql -lqtA | grep -q "^$DB_NAME|"
Một sự trở lại của true
( 0
) có nghĩa là nó tồn tại.
Nếu bạn nghi ngờ tên cơ sở dữ liệu của bạn có thể có một ký tự không chuẩn như $
, bạn cần một cách tiếp cận dài hơn một chút:
psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME"
Các tùy chọn -t
và -A
đảm bảo đầu ra là thô và không phải là "bảng" hoặc đầu ra có khoảng trắng. Các cột được phân tách bằng ký tự ống |
, do đó, cut
hoặc grep
phải nhận ra điều này. Cột đầu tiên chứa tên cơ sở dữ liệu.
EDIT: grep với -x để ngăn khớp tên một phần.
#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#
Để hoàn thiện, một phiên bản khác sử dụng regex thay vì cắt chuỗi:
psql -l | grep '^ exact_dbname\b'
Ví dụ:
if psql -l | grep '^ mydatabase\b' > /dev/null ; then
echo "Database exists already."
exit
fi
\b
có cùng một vấn đề như tất cả các câu trả lời sử dụng grep -w
đó là tên cơ sở dữ liệu có thể chứa các ký tự không cấu thành từ như thế -
và do đó các nỗ lực khớp foo
cũng sẽ khớp foo-bar
.
Câu trả lời được chấp nhận của kibibu là thiếu sót trong đó grep -w
sẽ khớp với bất kỳ tên nào có chứa mẫu được chỉ định làm thành phần từ.
tức là nếu bạn tìm "foo" thì "foo-backup" là khớp.
Câu trả lời của Otheus cung cấp một số cải tiến tốt và phiên bản ngắn sẽ hoạt động chính xác trong hầu hết các trường hợp, nhưng phiên bản dài hơn của hai biến thể được cung cấp cho thấy một vấn đề tương tự với chất nền phù hợp.
Để giải quyết vấn đề này, chúng tôi có thể sử dụng -x
đối số POSIX để chỉ khớp với toàn bộ dòng văn bản.
Dựa trên câu trả lời của Otheus, phiên bản mới trông như thế này:
psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"
Như đã nói, tôi muốn nói rằng câu trả lời của Nicolas Grilly - nơi bạn thực sự hỏi người đăng về cơ sở dữ liệu cụ thể - là cách tiếp cận tốt nhất trong tất cả.
Các giải pháp khác (rất tuyệt vời) bỏ lỡ thực tế là psql có thể đợi một phút hoặc hơn trước khi hết thời gian nếu nó không thể kết nối với máy chủ. Vì vậy, tôi thích giải pháp này, đặt thời gian chờ là 3 giây:
PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""
Điều này là để kết nối với một cơ sở dữ liệu phát triển trên hình ảnh chính thức của Dock Docker postgres .
Một cách riêng biệt, nếu bạn đang sử dụng Rails và muốn thiết lập cơ sở dữ liệu nếu nó chưa tồn tại (như khi khởi chạy một Docker container), thì điều này hoạt động tốt, vì việc di chuyển là tạm thời:
bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
Tôi vẫn còn khá thiếu kinh nghiệm với lập trình shell, vì vậy nếu điều này thực sự sai vì một số lý do, hãy bỏ phiếu cho tôi, nhưng đừng quá hoảng hốt.
Xây dựng từ câu trả lời của kibibu:
# If resulting string is not zero-length (not empty) then...
if [[ ! -z `psql -lqt | cut -d \| -f 1 | grep -w $DB_NAME` ]]; then
echo "Database $DB_NAME exists."
else
echo "No existing databases are named $DB_NAME."
fi
... | grep 0
để làm cho giá trị trả về shell là 0 nếu DB không tồn tại và 1 nếu có; hoặc... | grep 1
cho hành vi ngược lại