如何在 sqlplus 中将字符串结果用双引号引起来?

How to include double quotes around string result in sqlplus?

我们正在使用 SQL*Plus 将数据导出到 csv 文件。我们有小数列和文本列,每个字段都用逗号分隔 (,),但一些文本列也包含逗号。在将数据导入其他数据库时,我们看到文本中的这些逗号被视为列分隔符。谁能告诉我如何克服这个问题?

set tab off
SET head OFF
SET feedback OFF
SET pagesize 0
SET linesize 3000;
SET colsep ,
set trimspool on
set trimout on
set trims on
set null ""
set rowprefetch 2
set feedback off
set arraysize 1000
set PAGESIZE 50000
set STATEMENTCACHE 20
set numwidth 15
column coulmnName format 999999999.99
column coulmnName format 999999999.99
column coulmnName format 999999999.99
column coulmnName format 999999999.99

不要将列分隔符设置为逗号,而应设置为其他内容(例如竖线 | 或感叹号 ! 或井号 # 或其他一些不符合要求的字符存在于您即将导出的数据中)。当然,在将数据加载到目标数据库时,您会使用该符号作为分隔符。

只需将双引号字符连接到字符串数据类型的列的开头和结尾:

SELECT '"' || stringColumnA || '"' AS stringColumnA,
       numberColumnB,
       '"' || stringColumnC || '"' AS stringColumnC
       -- ...
FROM   table_name;

如果您的列已经包含双引号,则通过将它们加倍来转义它们:

SELECT '"' || REPLACE( stringColumnA, '"', '""' ) || '"' AS stringColumnA,
       numberColumnB,
       '"' || REPLACE( stringColumnC, '"', '""' ) || '"' AS stringColumnC
       -- ...
FROM   table_name;

如果您能够升级到 SQL*Plus 12.2,您可以使用 set markup csv on:

SQL> set markup csv on
SQL> select * from departments;

"DEPARTMENT_ID","DEPARTMENT_NAME","MANAGER_ID","LOCATION_ID"
10,"Administration",200,1700
20,"Marketing",201,1800
30,"Purchasing",114,1700
40,"Human Resources",203,2400
50,"Shipping",121,1500
60,"IT",103,1400
70,"Public Relations",204,2700
80,"Sales",145,2500
90,"Executive",100,1700
100,"Finance",108,1700

如果您处于 linux 环境中,您可以使用 ~ 作为分隔符,然后使用 sed 来修复输出。使用此方法,您不必知道 table 内容是什么即可创建 csv 文件。 下面的脚本包装 double-quotes 中的每个字段并删除尾随分隔符:

ORDER="01"
TABLE="MY_DATA_TBL"
CONN="127.0.0.1:31521/abc0008.world" #via ssh tunnel
sqlplus -L login/pswd@//${CONN}<<EOF >/dev/null
  set pagesize 4000;
  set verify off;
  set feedback off;
  set long 99999;
  set linesize 32767;
  set trimspool on;
  col object_ddl format A32000;
  set colsep ~;
  set underline off;
  set headsep off;
  spool ${ORD}${TABLE}.tmp1;
  select * from ${TABLE};
EOF
cat ${ORD}${TABLE}.tmp1 | sed -e "s/\"/'/" -e 's/ * / /g' -e "s/^ //" -e "s/ ~/~/g" -e "s/~ /~/g" | tail -n +11 | head -n -1 > ${ORD}${TABLE}.tmp2
head -n 1 ${ORD}${TABLE}.tmp2 | sed -e "s/$/~/" > ${ORD}${TABLE}.tmp3
tail -n +2 ${ORD}${TABLE}.tmp2 >> ${ORD}${TABLE}.tmp3
cat ${ORD}${TABLE}.tmp3 | sed -e "s/^/\"/" -e "s/~$/\"/" -e "s/~/\",\"/g" > ${ORD}${TABLE}.csv