Springboot使用spring.sql.init.schema-locations 初始化数据库脚本所遇问题(坑爹的PostgreSQL的美元符号)

一、场景

我需要在启动springboot应用的同时,在数据库中创建表和初始一些数据。

二、用法

其实实现这个需求有多种方式(这里我不多啰嗦,各位可以自行百度),我采用的是spring.sql.init.schema-locations配置创建数据库和主键索引的SQL语句,使用spring.sql.init.data-locations初始化表数据,使用简单明了。

spring.sql.init.schema-locations=classpath:sql/xxxx.sql
spring.sql.init.data-locations=classpath:sql/xxxx.sql
CREATE TABLE IF NOT EXISTS "t_counter" (
                             "id" varchar(36) COLLATE "pg_catalog"."default" NOT NULL,
                             "count" int4,
                             "url" varchar(255) COLLATE "pg_catalog"."default"
)
;
COMMENT ON COLUMN "t_counter"."count" IS '点击次数';
COMMENT ON COLUMN "t_counter"."url" IS '官网地址';
COMMENT ON TABLE "t_counter" IS '官网点击次数';


CREATE TABLE IF NOT EXISTS "t_reservation" (
                                 "id" varchar(36) COLLATE "pg_catalog"."default" NOT NULL,
                                 "corporate_name" varchar(200) COLLATE "pg_catalog"."default",
                                 "create_date" timestamp(6),
                                 "name" varchar(50) COLLATE "pg_catalog"."default",
                                 "phone_num" varchar(11) COLLATE "pg_catalog"."default"
)
;
COMMENT ON COLUMN "t_reservation"."corporate_name" IS '公司名称';
COMMENT ON COLUMN "t_reservation"."create_date" IS '创建时间';
COMMENT ON COLUMN "t_reservation"."name" IS '姓名';
COMMENT ON COLUMN "t_reservation"."phone_num" IS '电话';
COMMENT ON TABLE "t_reservation" IS '预约信息';

-- ----------------------------
-- Primary Key structure for table t_counter
-- ----------------------------
DO
$$
BEGIN
    IF NOT EXISTS (SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't_counter' AND constraint_name = 't_counter_pkey') THEN
        ALTER TABLE t_counter ADD CONSTRAINT t_counter_pkey PRIMARY KEY ("id");
    END IF;
END;
$$;


-- ----------------------------
-- Primary Key structure for table t_reservation
-- ----------------------------
DO
$$
BEGIN
    IF NOT EXISTS (SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't_reservation' AND constraint_name = 't_reservation_pkey') THEN
        ALTER TABLE t_reservation ADD CONSTRAINT t_reservation_pkey PRIMARY KEY ("id");
    END IF;
END;
$$;

是不是看着什么问题也没有,是不是很简单,我当时也是这么认为,而且我在navicat中执行也没有任何问题。

在这里插入图片描述

三、问题

结果天不如人愿,往往你认为越简单的东西,越会给你一些意想不到的结果。这不报错就来了吧!

Caused by: org.postgresql.util.PSQLException: Unterminated dollar quote started at position 3 in SQL DO $$ BEGIN IF NOT EXISTS (SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = ''t_counter'' AND constraint_name = ''t_counter_pkey'') THEN ALTER TABLE t_counter ADD CONSTRAINT t_counter_pkey PRIMARY KEY ("id"). Expected terminating $$
	at org.postgresql.core.Parser.checkParsePosition(Parser.java:1443) ~[postgresql-42.6.2.jar:42.6.2]
	at org.postgresql.core.Parser.parseSql(Parser.java:1342) ~[postgresql-42.6.2.jar:42.6.2]
	at org.postgresql.core.Parser.replaceProcessing(Parser.java:1294) ~[postgresql-42.6.2.jar:42.6.2]
	at org.postgresql.core.CachedQueryCreateAction.create(CachedQueryCreateAction.java:43) ~[postgresql-42.6.2.jar:42.6.2]
	at org.postgresql.core.QueryExecutorBase.createQueryByKey(QueryExecutorBase.java:369) ~[postgresql-42.6.2.jar:42.6.2]
	at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:313) ~[postgresql-42.6.2.jar:42.6.2]
	at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:297) ~[postgresql-42.6.2.jar:42.6.2]
	at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:292) ~[postgresql-42.6.2.jar:42.6.2]
	at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:94) ~[HikariCP-5.0.1.jar:na]
	at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-5.0.1.jar:na]
	at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:261) ~[spring-jdbc-6.1.8.jar:6.1.8]
	... 27 common frames omitted

在这里插入图片描述
看到这个问题,首先感觉就是,这都会报错?

赶紧翻译一下:未终止的 $ 符号从sql语句中的第3位开始。预期终止 $

说人话就是,没有以$$ 结束语句??

在这里插入图片描述
赶紧分析一下,我语句没有问题,navicat可以执行,那只能是spring在解析sql语句后执行出错了。可能解析的语句不是pgsql的语法。

四、如何解决

在网上找了找问题解决办法,搜索Unterminated dollar quote started at position 3 in SQL,居然第一篇文章就是解决这个问题的,
万能的stack overflow。。

在这里插入图片描述

For platforms that don't recognize dollar quoting you can use ' instead. You'll need to escape any ' in the body of the anonymous function though.

意思是:对于不认可$$符号的平台,您可以使用 ‘’ 代替。不过,您需要转义匿名函数主体中的任何单引号改为两个单引号’‘’'。
在这里插入图片描述
按照上述说明修改我自己的sql语句:

-- ----------------------------
-- Primary Key structure for table t_counter
-- ----------------------------
DO
'
BEGIN
    IF NOT EXISTS (SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = ''t_counter'' AND constraint_name = ''t_counter_pkey'') THEN
        ALTER TABLE t_counter ADD CONSTRAINT t_counter_pkey PRIMARY KEY ("id");
    END IF;
END;
';


-- ----------------------------
-- Primary Key structure for table t_reservation
-- ----------------------------
DO
'
BEGIN
    IF NOT EXISTS (SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = ''t_reservation'' AND constraint_name = ''t_reservation_pkey'') THEN
        ALTER TABLE t_reservation ADD CONSTRAINT t_reservation_pkey PRIMARY KEY ("id");
    END IF;
END;
';

完美运行!!!!!搞定!!!

在此记录一下,避免忘记。。。愿工作中没有BUG!!!!

如果您需要在`spring.datasource.sql.init.schema-locations`中执行`DROP DATABASE IF EXISTS`和`CREATE DATABASE IF NOT EXISTS`这些语句来创建数据库,可以按照以下步骤操作: 1. 在您的SQL脚本中添加`DROP DATABASE IF EXISTS`和`CREATE DATABASE IF NOT EXISTS`语句,例如: ```sql DROP DATABASE IF EXISTS `spring_batch`; CREATE DATABASE IF NOT EXISTS `spring_batch` CHARACTER SET UTF8; USE `spring_batch`; ``` 2. 在application.properties或application.yml中配置数据库访问凭据和权限,例如: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=123456 ``` 3. 在application.properties或application.yml中配置`spring.datasource.initialization-mode=always`,以启用SQL初始化脚本的自动执行,例如: ```properties spring.datasource.initialization-mode=always ``` 4. 将包含SQL脚本的文件放置在`src/main/resources`目录下,并在`spring.datasource.sql.init.schema-locations`中指定该文件的路径,例如: ```properties spring.datasource.sql.init.schema-locations=classpath:db/schema.sql ``` 5. 启动应用程序,SQL脚本将在应用程序启动时自动执行,数据库将被创建或更新。 需要注意的是,在实际生产环境中,不建议在SQL脚本使用`DROP DATABASE IF EXISTS`和`CREATE DATABASE IF NOT EXISTS`语句,因为这可能会导致数据丢失或安全问题。在生产环境中,最好由DBA或系统管理员手动创建和维护数据库
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值