如何用Liquibase向PostgreSQL插入带换行符的字符串?
问题分析与解决方案
问题根源
- Liquibase的
loadData默认以\作为转义字符,会自动解析CSV中的转义序列:第一行的'\n'被转义处理后丢失反斜杠,最终变成nStarts 25.01.2021 n nin; - 第二行的
'\\n'在CSV中被转义为单个\,因此数据库中存储的是\n,但Java读取时会用\\表示单个\(这是Java字符串的正常转义显示,实际存储内容是正确的)。
解决方案
方案1:禁用Liquibase转义处理
修改loadData标签,添加escapeChar属性并设置为空,让CSV中的\直接作为字面量插入:
<changeSet id="insert_consents" author="Alex" > <loadData tableName="consents" relativeToChangelogFile="false" separator=";" file="db/changelog/dictionaries/consents.csv" quotchar="'" escapeChar=""> </loadData> </changeSet>
此时CSV的text列保持为'\nStarts 25.01.2021 \n\nin'即可,无需额外转义。
方案2:直接用SQL插入(精确可控)
改用sql标签,利用PostgreSQL的美元引号语法避免转义问题,确保插入的字符串完全符合预期:
<changeSet id="insert_consents" author="Alex" > <sql> INSERT INTO consents (scenario_id, text) VALUES (123, $$\nStarts 25.01.2021 \n\nin$$), (456, $$\nStarts 25.01.2021 \n\nin$$); </sql> </changeSet>
美元引号$$包裹的字符串中,\会被直接当作普通字符存储,插入后数据库和Java读取的结果均符合要求(Java中显示\\n是字符串的转义表示,实际存储为单个\)。
方案3:调整CSV内容的转义方式
如果不想修改Liquibase配置,可在CSV中用双重反斜杠表示单个反斜杠,即text列写为'\\nStarts 25.01.2021 \\n\\nin',Liquibase解析后会将\\转换为单个\,最终插入正确的字面量字符串。
内容的提问来源于stack exchange,提问作者petrov.aleksandr
相关产品推荐
相关产品推荐

