解析 JSON 时出现雪花错误,因为单引号未转义
Snowflake error on parsing JSON as single quotes are not escaped
我在处理 Snowflake 数据仓库中的一些数据时尝试记录错误。
我在特定数据文件上遇到的错误如下,我需要将其放入名为 DATA_LOAD_LOG
:
的 table 中
INSERT INTO DWH_OPS.DATA_LOAD_LOG select 'DATA LOAD PROCEDURE', ?, ?,
(datediff('milliseconds', ?, ?)/1000), current_schema(),
current_database(), current_user(), current_role(), ?,
parse_json('[{"Error":"Can't parse 'n/a' as date with format
'YYYY-MM-DD'","Survey Name":"data.csv","Stage
Name":"@DWH_OPS.AZURE_BLOB","Execution Duration (in
seconds)":5.405}]')::VARIANT
错误信息是:
"Can't parse 'n/a' as date with format 'YYYY-MM-DD'"
catch 部分返回不同的语法错误,因为 t
和 'YYYY-MM-DD'
之前有单引号。所以日志没有添加到 table.
这里是捕获部分脚本:
try {
// Try code
} catch (err) {
var obj = {};
var res = [];
obj["Error"] = "Exists";
obj["Error Message"] = err.message;
obj["Status"] = err.status;
obj["Error Code"] = err.code;
res.push(obj);
var insert_into_data_log =
"INSERT INTO DWH_OPS.DATA_LOAD_LOG select 'DATA LOAD PROCEDURE', current_timestamp(), " +
"current_timestamp(), 0, " +
"current_schema(), current_database(), current_user(), current_role(), " +
"'SCRIPT ERROR', parse_json('" +
JSON.stringify(res) +
"')::VARIANT";
var data_log_stmt = snowflake
.createStatement({ sqlText: insert_into_data_log })
.execute();
return err;
}
我尝试用 space 替换或使用以下方法转义它:
var errorMsg = err.message; obj['Error Message'] =
errorMsg.replace("'","").replace("."," ").replace("\n"," ");
但它根本不起作用,并且抛出了同样的错误。
您可以使用此方法对单引号进行转义:
obj["Error Message"] = obj["Error Message"].replace(/'/g, "\''");
这里有一个简单的测试脚本:
create table DATA_LOAD_LOG ( t timestamp, v variant );
create or replace procedure test_sp()
returns string
language javascript
as
$$
var obj = {};
var res = [];
obj["Error"] = "Exists";
obj["Error Message"] = "Can't parse 'n/a' as date with format 'YYYY-MM-DD'";
obj["Error Message"] = obj["Error Message"].replace(/'/g, "\''");
obj["Error Code"] = 200;
res.push(obj);
var insert_into_data_log =
"INSERT INTO DATA_LOAD_LOG select current_timestamp(), " +
"parse_json('" + JSON.stringify(res) + "')::VARIANT";
var data_log_stmt = snowflake.createStatement({ sqlText: insert_into_data_log }).execute();
return "Ok";
$$;
call test_sp();
如果您打算通过构造 SQL 而不是使用绑定变量来直接插入字符串和日期,那么您需要转义的不仅仅是单引号。您还必须至少转义反斜杠和换行符。这是您可以用来执行此操作的辅助函数。
function escapeString(str){
str = str.replace(/'/g, "''");
str = str.replace(/\/g, "\\");
str = str.replace(/(\r\n|\n|\r)/gm," ");
return str;
}
在您的 SP 中使用:
try {
// Try code
} catch (err) {
var obj = {};
var res = [];
obj["Error"] = "Exists";
obj["Error Message"] = escapeString(err.message);
obj["Status"] = escapeString(err.status);
obj["Error Code"] = err.code;
res.push(obj);
var insert_into_data_log =
"INSERT INTO DWH_OPS.DATA_LOAD_LOG select 'DATA LOAD PROCEDURE', current_timestamp(), " +
"current_timestamp(), 0, " +
"current_schema(), current_database(), current_user(), current_role(), " +
"'SCRIPT ERROR', parse_json('" +
JSON.stringify(res) +
"')::VARIANT";
var data_log_stmt = snowflake
.createStatement({ sqlText: insert_into_data_log })
.execute();
return err;
function escapeString(str){
str = str.replace(/'/g, "''");
str = str.replace(/\/g, "\\");
str = str.replace(/(\r\n|\n|\r)/gm," ");
return str;
}
}
我在处理 Snowflake 数据仓库中的一些数据时尝试记录错误。
我在特定数据文件上遇到的错误如下,我需要将其放入名为 DATA_LOAD_LOG
:
INSERT INTO DWH_OPS.DATA_LOAD_LOG select 'DATA LOAD PROCEDURE', ?, ?, (datediff('milliseconds', ?, ?)/1000), current_schema(), current_database(), current_user(), current_role(), ?, parse_json('[{"Error":"Can't parse 'n/a' as date with format 'YYYY-MM-DD'","Survey Name":"data.csv","Stage Name":"@DWH_OPS.AZURE_BLOB","Execution Duration (in seconds)":5.405}]')::VARIANT
错误信息是:
"Can't parse 'n/a' as date with format 'YYYY-MM-DD'"
catch 部分返回不同的语法错误,因为 t
和 'YYYY-MM-DD'
之前有单引号。所以日志没有添加到 table.
这里是捕获部分脚本:
try {
// Try code
} catch (err) {
var obj = {};
var res = [];
obj["Error"] = "Exists";
obj["Error Message"] = err.message;
obj["Status"] = err.status;
obj["Error Code"] = err.code;
res.push(obj);
var insert_into_data_log =
"INSERT INTO DWH_OPS.DATA_LOAD_LOG select 'DATA LOAD PROCEDURE', current_timestamp(), " +
"current_timestamp(), 0, " +
"current_schema(), current_database(), current_user(), current_role(), " +
"'SCRIPT ERROR', parse_json('" +
JSON.stringify(res) +
"')::VARIANT";
var data_log_stmt = snowflake
.createStatement({ sqlText: insert_into_data_log })
.execute();
return err;
}
我尝试用 space 替换或使用以下方法转义它:
var errorMsg = err.message; obj['Error Message'] = errorMsg.replace("'","").replace("."," ").replace("\n"," ");
但它根本不起作用,并且抛出了同样的错误。
您可以使用此方法对单引号进行转义:
obj["Error Message"] = obj["Error Message"].replace(/'/g, "\''");
这里有一个简单的测试脚本:
create table DATA_LOAD_LOG ( t timestamp, v variant );
create or replace procedure test_sp()
returns string
language javascript
as
$$
var obj = {};
var res = [];
obj["Error"] = "Exists";
obj["Error Message"] = "Can't parse 'n/a' as date with format 'YYYY-MM-DD'";
obj["Error Message"] = obj["Error Message"].replace(/'/g, "\''");
obj["Error Code"] = 200;
res.push(obj);
var insert_into_data_log =
"INSERT INTO DATA_LOAD_LOG select current_timestamp(), " +
"parse_json('" + JSON.stringify(res) + "')::VARIANT";
var data_log_stmt = snowflake.createStatement({ sqlText: insert_into_data_log }).execute();
return "Ok";
$$;
call test_sp();
如果您打算通过构造 SQL 而不是使用绑定变量来直接插入字符串和日期,那么您需要转义的不仅仅是单引号。您还必须至少转义反斜杠和换行符。这是您可以用来执行此操作的辅助函数。
function escapeString(str){
str = str.replace(/'/g, "''");
str = str.replace(/\/g, "\\");
str = str.replace(/(\r\n|\n|\r)/gm," ");
return str;
}
在您的 SP 中使用:
try {
// Try code
} catch (err) {
var obj = {};
var res = [];
obj["Error"] = "Exists";
obj["Error Message"] = escapeString(err.message);
obj["Status"] = escapeString(err.status);
obj["Error Code"] = err.code;
res.push(obj);
var insert_into_data_log =
"INSERT INTO DWH_OPS.DATA_LOAD_LOG select 'DATA LOAD PROCEDURE', current_timestamp(), " +
"current_timestamp(), 0, " +
"current_schema(), current_database(), current_user(), current_role(), " +
"'SCRIPT ERROR', parse_json('" +
JSON.stringify(res) +
"')::VARIANT";
var data_log_stmt = snowflake
.createStatement({ sqlText: insert_into_data_log })
.execute();
return err;
function escapeString(str){
str = str.replace(/'/g, "''");
str = str.replace(/\/g, "\\");
str = str.replace(/(\r\n|\n|\r)/gm," ");
return str;
}
}