我正在 for 循环中自动处理 ci 解决方案中带有 bash 的.sql文件,以便在部署之前捕获错误的迁移。
MIGS 是一个 bash 数组,按时间顺序包含文件夹中.sql
for sqlfile in ${MIGS[@]};
do
psql myproject_unit < $sqlfile
done
如果满足条件,有没有办法终止.sql的处理?
所以我现在做什么:
文件SQL20180515N.sql
CREATE TABLE IF NOT EXISTS something (
...
/* imagine here other 400 lines of SQL */
我正在寻找什么(如果适用,请将前两行替换为正确的语法,或者告诉我如果不可能(
IF TABLE_EXISTS(something) /* we already ran, no need */
EXIT;
CREATE TABLE something (
...
/* imagine here other 400 lines of SQL */
所以为了确认:如果满足条件(表/col/触发器/索引已经存在(,我想跳到我的 for 循环中的下一个.sql源,所以不要退出整个 shell,只是退出 .sql 文件中定义的 psql 处理器何时终止它。
你很可能需要plpgsql逻辑,因此DO
语句,下面是一个例子:
MacBook-Air:Downloads vao$ psql so << EOF
> do $$
> begin
> if (select count(*) from pg_class where oid = 'public.t'::regclass and relkind = 'r') > 0 then
> insert into t values(1);
> update t set i = 9 where i = 1;
> end if;
> end;
> $$;
> select * from t;
> EOF
Timing is on.
Pager usage is off.
DO
Time: 8.952 ms
i
---
9
9
9
(3 rows)
PlPgsql 对其进行排序,我们使用以下代码作为示例开始。
-- USE THIS AS EXAMPLE CODE FOR CREATING MORE COMPLEX TABLE STRUSCTURES NEVER TO BE DEFINED TWICE
CREATE OR REPLACE FUNCTION install_these_tables()
RETURNS INT AS $$
DECLARE
does_exist int;
BEGIN
SELECT COUNT(*) as cnt INTO does_exist from pg_tables where tablename = 'testtable'; -- REPLACE TABLE NAME
IF does_exist = 1 THEN
RAISE NOTICE 'Existed';
RETURN 1;
ELSE
-- REPLACE START
CREATE TABLE testtable (
id_testtable bigserial PRIMARY KEY,
status text DEFAULT NULL
);
-- REPLACE END
RAISE NOTICE 'Not existed, created';
RETURN 0;
END IF;
END; $$ LANGUAGE plpgsql;
SELECT install_these_tables();
DROP FUNCTION install_these_tables();
PostgreSQL 10 也支持 \if,但我们使用 9.6,也没有发现容易更改示例代码
其他答案很好,但也许你更愿意将你的逻辑保留在shell中。
您可以在单独的psql
调用中查询条件。
在下面的示例中,我测试表something
是否存在:
psql -d mydb -c "SELECT 'something'::regclass" >/dev/null 2>&1
# run the script only if the above errors out
if [ $? -ne 0 ]; then
# create "something" since it doesn't exist
psql -d mydb -1 -f create_something.sql
if [ $? -ne 0 ]; then
# exit with error if script fails
exit 1
fi
fi