存储过程变量中存储SQL语句被截断的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了存储过程变量中存储SQL语句被截断的问题相关的知识,希望对你有一定的参考价值。
@SQL中存储一段动态SQL
where条件获取动态参数,执行@SQL就被截断,把where写死就能执行成功。
例, set=@name='Tom'
set @SQL='select * from tab where name =''@name'' ' 失败
set @SQL='select * from tab where name =''Tom'' ' 成功
当然我的@SQL非常长,LEN=30000多。
是我没写清楚,set @SQL='select * from tab where name ='''+@name+''''就是这样,@SQL和@name的类型都是NVARCHAR(MAX),print 输出的结果是一条被截断的SQL语句,print len(@sql)=30000,就是set @name='TOM'就截断SQL语句,直接在里面写死就可以,不知道为什么
mysql一般先拼接好SQL,再执行,如下:
set conditions = "select * from table where 1 ";
set conditions = concat(conditions," and id=",1);
set @sql = conditions;
sqlserver一般做拼接的话,如下:
set @sql = 'select * FROM tab where name = @name'追问
用SQLServer
是我没写清楚,set @SQL='select * from tab where name ='''+@name+''''就是这样,@SQL和@name的类型都是NVARCHAR(MAX),print 输出的结果是一条被截断的SQL语句,print len(@sql)=30000,就是set @name='TOM'就截断SQL语句,直接在里面写死就可以,不知道为什么
换成下面这样的
set @SQL='select * from tab where name ='''+@name+''''
以后测试的时候,可以在set完后,加条语句print @SQL,看看是什么结果,这个一般就是执行时候的语句追问
是我没写清楚,set @SQL='select * from tab where name ='''+@name+''''就是这样,@SQL和@name的类型都是NVARCHAR(MAX),print 输出的结果是一条被截断的SQL语句,print len(@sql)=30000,就是set @name='TOM'就截断SQL语句,直接在里面写死就可以,不知道为什么
追答为什么要设置成nvarchar(max)?你什么字符要这么大啊,几百几千就可以了,没有中文全字符就varchar(???)这样啊
追问开发规范就这样,要用NVARCHAR,另外我的SQL却是非常长,大概10万个字符左右
追答那个@name里面的数据可能有问题吧,可以print @name print @SQL这样一个一个的查看啊,总会找到错误的
追问print @SQL 显示的是一个被截断的SQL
追答那就是太长了还是怎么的
参考技术B set @SQL='select * from tab where name ='+@name追问是我没写清楚,set @SQL='select * from tab where name ='''+@name+''''就是这样,@SQL和@name的类型都是NVARCHAR(MAX),print 输出的结果是一条被截断的SQL语句,print len(@sql)=30000,就是set @name='TOM'就截断SQL语句,直接在里面写死就可以,不知道为什么
db2存储过程动态sql被截断
编写存储过程,使用动态sql时,调试时发现变量赋值后被截断。
关键代码如下:
实现的效果是先把上下游做对比的sql语句和相关参数存入RKDM_DATA_VOID_RULE,
执行存储过程后把两个sql语句得出的结果插入另一张结果表RKDM_DATA_VOID_CHK_REST。
建表语句:
CREATE TABLE RKDM_DATA_VOID_CHK_REST (
DATA_DT DATE,
ORDR_NUM INTEGER,
CHK_BIG_CLS VARCHAR(256),
DATA_PRTN VARCHAR(80),
SBJ VARCHAR(256),
ENT_EN VARCHAR(256),
ENT_CN VARCHAR(200),
FLD_EN VARCHAR(100),
FLD_CN VARCHAR(256),
FWD_CHK_SQL VARCHAR(500),
REV_CHK_SQL VARCHAR(500),
CD_TAB VARCHAR(100),
CD_FLD VARCHAR(100),
CHK_AIM VARCHAR(50),
CHK_COMNT VARCHAR(50),
FWD_CHK_RSLT VARCHAR(500),
REV_CHK_RSLT VARCHAR(500),
NULL_CNT INTEGER,
CD_VAL VARCHAR(50),
ERR_CNT INTEGER
)
;
COMMENT ON TABLE RKDM_DATA_VOID_CHK_REST IS ‘数据质量检查结果‘;
COMMENT ON RKDM_DATA_VOID_CHK_REST (
DATA_DT IS ‘数据日期‘,
ORDR_NUM IS ‘序号‘,
CHK_BIG_CLS IS ‘检查类型‘,
DATA_PRTN IS ‘数据分区‘,
SBJ IS ‘主题‘,
ENT_EN IS ‘实体英文名‘,
ENT_CN IS ‘实体中文名‘,
FLD_EN IS ‘字段英文名‘,
FLD_CN IS ‘字段中文名‘,
FWD_CHK_SQL IS ‘上游/正向检查SQL‘,
REV_CHK_SQL IS ‘下游/反向检查SQL‘,
CD_TAB IS ‘代码表‘,
CD_FLD IS ‘代码字段‘,
CHK_AIM IS ‘检查目的‘,
CHK_COMNT IS ‘检查说明‘,
FWD_CHK_RSLT IS ‘上游/正向检查结果‘,
REV_CHK_RSLT IS ‘下游/反向检查结果‘,
NULL_CNT IS ‘空值数‘,
CD_VAL IS ‘代码值‘,
ERR_CNT IS ‘异常条数‘ );
CREATE TABLE RKDM_DATA_VOID_RULE (
ORDR_NUM INTEGER,
CHK_BIG_CLS VARCHAR(256),
DATA_PRTN VARCHAR(80),
SBJ VARCHAR(256),
ENT_EN VARCHAR(256),
ENT_CN VARCHAR(200),
FLD_EN VARCHAR(100),
FLD_CN VARCHAR(256),
FWD_CHK_SQL VARCHAR(500),
REV_CHK_SQL VARCHAR(500),
CD_TAB VARCHAR(100),
CD_FLD VARCHAR(100),
CHK_AIM VARCHAR(500),
CHK_COMNT VARCHAR(500)
)
;
COMMENT ON TABLE RKDM_DATA_VOID_RULE IS ‘数据质量检查规则‘;
COMMENT ON RKDM_DATA_VOID_RULE (
ORDR_NUM IS ‘序号‘,
CHK_BIG_CLS IS ‘检查类型‘,
DATA_PRTN IS ‘数据分区‘,
SBJ IS ‘主题‘,
ENT_EN IS ‘实体英文名‘,
ENT_CN IS ‘实体中文名‘,
FLD_EN IS ‘字段英文名‘,
FLD_CN IS ‘字段中文名‘,
FWD_CHK_SQL IS ‘上游/正向检查SQL‘,
REV_CHK_SQL IS ‘下游/反向检查SQL‘,
CD_TAB IS ‘代码表‘,
CD_FLD IS ‘代码字段‘,
CHK_AIM IS ‘检查目的‘,
CHK_COMNT IS ‘检查说明‘ );
数据:
INSERT INTO RKDM_DATA_VOID_RULE
(Ordr_Num,Chk_Big_Cls,Data_Prtn,Sbj,Ent_EN,Ent_CN,FLD_EN,FLD_CN,Fwd_Chk_SQL,Rev_Chk_SQL,Chk_Aim)
VALUES (‘1‘,
‘关键指标检核_上下游比对‘,
‘零售‘,
‘参与主体‘,
‘TB_RZT_CUST_ACCT_STATS‘,
‘客户账户统计‘,
‘Dmnd_Dpst_Acct_Cnt‘,
‘活期存款账户数‘,
‘SELECT COUNT(1) FROM TEST_T_APP_2 WHERE B=‘‘2‘‘‘,
‘SELECT COUNT(1) FROM TEST_T_APP_3‘,
‘通过对客户账户统计表的活期存款账户数字段源和目标的检核,确认处理逻辑是否存在问题‘);
INSERT INTO RKDM_DATA_VOID_RULE
(Ordr_Num,Chk_Big_Cls,Data_Prtn,Sbj,Ent_EN,Ent_CN,FLD_EN,FLD_CN,Fwd_Chk_SQL,Rev_Chk_SQL,Chk_Aim)
VALUES (‘2‘,
‘关键指标检核_上下游比对‘,
‘零售‘,
‘参与主体‘,
‘TB_RZT_CUST_ACCT_STATS‘,
‘客户账户统计‘,
‘Mtg_Loan_Acct_Cnt‘,
‘按揭贷款账户数‘,
‘SELECT COUNT(1) FROM TEST_T_APP_2 WHERE B=‘‘1‘‘‘,
‘SELECT COUNT(1) FROM TEST_T_APP_3 WHERE B IS NOT NULL‘,
‘通过对客户账户统计表的按揭贷款账户数字段源和目标的检核,确认处理逻辑是否存在问题‘);
存储过程代码:
CREATE OR REPLACE PROCEDURE RKDM_KEY_INDX_CHK(
IN in_data_dt VARCHAR(10),
OUT out_succeed INTEGER
)
DYNAMIC RESULT SETS 1
/******************************************************************************
程序名称:RKDM_KEY_INDX_CHK
功能描述:关键指标测试_上下游比对
输入参数:in_data_dt 数据日期
输出参数:out_succeed 是否成功标志。1-失败 0-成功
作者:
版本号:V1.0.0.0
修改历史:
版本 更改日期 更新人 更新说明
******************************************************************************/
P1:BEGIN
/*************标准定义变量**************************************************/
DECLARE v_job_name VARCHAR(60) DEFAULT ‘CLEAN_DATA‘; --作业名称
DECLARE v_point VARCHAR(10); --记录点
DECLARE v_start_tm TIMESTAMP; --开始执行时间
DECLARE v_end_tm TIMESTAMP; --结束执行时间
DECLARE v_sql VARCHAR(20000); --执行SQL
DECLARE v_ex_sql_log VARCHAR(20000); --执行SQL
DECLARE v_run_result VARCHAR(20); --执行结果
DECLARE v_date VARCHAR(10); --数据日期
DECLARE v_msg VARCHAR(10); --错误信息
DECLARE SQLCODE INT DEFAULT 0; --显示定义数据库变量SQLCODE
DECLARE SQLSTATE CHAR(5) DEFAULT ‘0000‘; --显示定义数据库变量SQLSTATE
DECLARE v_etl_owner VARCHAR(20) DEFAULT ‘ETL‘; --本SP操作的用户
/**************定义常用日期变量**********************************************/
DECLARE V_T_YEAR VARCHAR(4); --本年
DECLARE V_T_MONTH VARCHAR(8); --本月
DECLARE V_T_DAY VARCHAR(8); --本日
DECLARE V_L_YEAR VARCHAR(4); --去年
DECLARE V_F_TX_DATE DATE; --标准日期
DECLARE V_F_C_DATE VARCHAR(10); --十位标准日期字符串格式
DECLARE V_LAST_DAY VARCHAR(8); --上一日
DECLARE V_NEXT_MON_START VARCHAR(8); --下月初
DECLARE V_MON_START VARCHAR(8); --本月初
DECLARE V_MON_END VARCHAR(8); --本月末
DECLARE V_LAST_MON_END VARCHAR(8); --上月末
DECLARE V_BEGIN_YEAR VARCHAR(8); --年初
DECLARE V_LAST_YEAR_END VARCHAR(8); --上年末
DECLARE V_LAST_YEAR_PERIOD VARCHAR(8); --去年同期
DECLARE V_QUARTER VARCHAR(8); --所在季度数 V_QUERTER
DECLARE V_BEGIN_QUARTER VARCHAR(8); --季初
DECLARE V_TH_LAST_MON_END VARCHAR(8); --上上上月末
DECLARE V_TH_LAST_YEAR_END VARCHAR(8); --上上上年末
/**************自定义变量***************************************************/
DECLARE V_DATA_COUNT_PRE INTEGER;
DECLARE DATA_DT VARCHAR(8); --数据日期
DECLARE ETL_DT VARCHAR(8); --ETL处理日期(当前日期)
DECLARE ADD_DT VARCHAR(8); --增量日期
DECLARE MAXDATE VARCHAR(8); --最大日期
DECLARE ILLDATE VARCHAR(8); --错误日期
DECLARE NULLDATE VARCHAR(8); --空日期
DECLARE NULLSTRING VARCHAR(1); --空字符串
DECLARE NULLNUMBER VARCHAR(1); --空数值
DECLARE NULLTIME TIME; --空时间
DECLARE NULLTIMESTAMP TIMESTAMP; --空时间戳
DECLARE v_sql_del VARCHAR(20000); --执行SQL
DECLARE v_sql_fwd VARCHAR(20000); --执行SQL
DECLARE v_sql_rev VARCHAR(20000); --执行SQL
DECLARE v_sql_insert VARCHAR(30000); --执行SQL
DECLARE VAL_FWD VARCHAR(10);
DECLARE VAL_REV VARCHAR(10);
DECLARE RS_STMT_FWD STATEMENT;
DECLARE RS_STMT_REV STATEMENT;
DECLARE RS_C_FWD CURSOR FOR RS_STMT_FWD;
DECLARE RS_C_REV CURSOR FOR RS_STMT_REV;
/**************异常处理******************************************************/
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS EXCEPTION 1 v_msg = MESSAGE_TEXT;
SET out_succeed = 1;
SET v_run_result = ‘执行失败‘;
SET v_msg = ‘SQLCODE:‘||rtrim(CHAR(SQLCODE))||‘.SQLSTATE:‘||SQLSTATE||‘‘||v_msg;
SET v_end_tm = current timestamp;
ROLLBACK;
END;
/**************标准变量处理**************************************************/
SET v_start_tm = current timestamp;
SET v_date = in_data_dt;
SET out_succeed = 0;
SET v_run_result = ‘执行成功‘;
SET v_job_name = ‘CLEAN_DATA‘;
--自定义参数赋值
VALUES in_data_dt INTO DATA_DT;
VALUES to_char(current date,‘YYYYMMDD‘) INTO ETL_DT;
VALUES in_data_dt INTO ADD_DT;
VALUES ‘89991231‘ INTO MAXDATE;
VALUES ‘00010102‘ INTO ILLDATE;
VALUES ‘00010101‘ INTO NULLDATE;
VALUES ‘‘ INTO NULLSTRING;
VALUES 0 INTO NULLNUMBER;
VALUES ‘00:00:00‘ INTO NULLTIME;
VALUES ‘0001-01-01 00:00:00.000000‘ INTO NULLTIMESTAMP;
--自定义日期参数赋值
VALUES substr(in_data_dt,1,4) INTO V_T_YEAR; --本年
VALUES substr(in_data_dt,5,2) INTO V_T_MONTH; --本月
VALUES substr(in_data_dt,7,2) INTO V_T_DAY; --本日
VALUES substr(in_data_dt,1,4)-1 INTO V_L_YEAR; --去年
VALUES to_date(in_data_dt,‘yyyy-mm-dd‘) INTO V_F_TX_DATE; --标准日期
VALUES to_char(to_date(in_data_dt,‘yyyy-mm-dd‘),‘yyyy-mm-dd‘) INTO V_F_C_DATE; --十位标准日期字符串格式
VALUES to_char(to_date(in_data_dt,‘yyyymmdd‘)-1 day,‘yyyymmdd‘) INTO V_LAST_DAY; --上一日
--VALUES to_char(last_day(to_date(in_data_dt,‘yyyymmdd‘))+1 day,‘yyyymmdd‘) INTO V_NEXT_MON_START; --下月初
VALUES V_T_YEAR||V_T_MONTH||‘01‘ INTO V_MON_START; --本月初
--VALUES to_char(last_day(to_date(in_data_dt,‘yyyymmdd‘),‘yyyymmdd‘),‘yyyymmdd‘) INTO V_MON_END; --本月末
VALUES to_char(to_date(V_MON_START,‘yyyymmdd‘)-1 day,‘yyyymmdd‘) INTO V_LAST_MON_END; --上月末
VALUES to_char(to_date(V_T_YEAR||‘-01-01‘,‘yyyymmdd‘),‘yyyymmdd‘) INTO V_BEGIN_YEAR; --年初
VALUES to_char(to_date(V_BEGIN_YEAR,‘yyyymmdd‘)-1 day,‘yyyymmdd‘) INTO V_LAST_YEAR_END; --上年末
VALUES to_char(to_date(in_data_dt,‘yyyymmdd‘)-12 month,‘yyyymmdd‘) INTO V_LAST_YEAR_PERIOD; --去年同期
VALUES CASE WHEN V_T_MONTH IN (‘01‘,‘02‘,‘03‘) THEN ‘1‘
WHEN V_T_MONTH IN (‘04‘,‘05‘,‘06‘) THEN ‘2‘
WHEN V_T_MONTH IN (‘07‘,‘08‘,‘09‘) THEN ‘3‘
WHEN V_T_MONTH IN (‘10‘,‘11‘,‘12‘) THEN ‘4‘
END INTO V_QUARTER; --所在季度
VALUES CASE V_QUARTER
WHEN ‘1‘ THEN V_T_YEAR||‘0101‘
WHEN ‘2‘ THEN V_T_YEAR||‘0401‘
WHEN ‘3‘ THEN V_T_YEAR||‘0701‘
WHEN ‘4‘ THEN V_T_YEAR||‘1001‘
END INTO V_BEGIN_QUARTER; --季初
VALUES to_char(last_day(to_date(in_data_dt,‘yyyymmdd‘)-3 month),‘yyyymmdd‘) INTO V_TH_LAST_MON_END; --上上上月末
VALUES to_char(year(to_date(in_data_dt,‘yyyymmdd‘)-3 year)||‘-01-01‘,‘yyyymmdd‘) INTO V_TH_LAST_YEAR_END; --上上上年末
/**************脚本主要逻辑**************************************************/
--防重跑,先删除数据
SET v_sql_del=‘DELETE FROM RKDM_DATA_VOID_CHK_REST WHERE DATA_DT=‘‘‘||v_date||‘‘‘ AND Chk_Big_Cls=‘‘关键指标检核_上下游比对‘‘‘;
PREPARE DEL_STMT FROM v_sql_del;
EXECUTE DEL_STMT;
--循环检查规则
FOR RS_LOOP AS
SELECT Ordr_Num as Ordr_Num,
Chk_Big_Cls as Chk_Big_Cls,
Data_Prtn as Data_Prtn,
Sbj as Sbj,
Ent_EN as Ent_EN,
Ent_CN as Ent_CN,
FLD_EN as FLD_EN,
FLD_CN as FLD_CN,
Fwd_Chk_SQL as Fwd_Chk_SQL,
Rev_Chk_SQL as Rev_Chk_SQL,
Chk_Aim as Chk_Aim
FROM RKDM_DATA_VOID_RULE WHERE Chk_Big_Cls=‘关键指标检核_上下游比对‘
DO
SET v_sql_fwd=RS_LOOP.Fwd_Chk_SQL;
SET v_sql_rev=RS_LOOP.Rev_Chk_SQL;
PREPARE RS_STMT_FWD FROM v_sql_fwd;
OPEN RS_C_FWD;
PREPARE RS_STMT_REV FROM v_sql_rev;
OPEN RS_C_REV;
FETCH RS_C_FWD INTO VAL_FWD;
FETCH RS_C_REV INTO VAL_REV;
CLOSE RS_C_FWD;
CLOSE RS_C_REV;
SET v_sql_insert=‘INSERT INTO RKDM_DATA_VOID_CHK_REST(DATA_DT,Chk_Big_Cls,Ordr_Num,Data_Prtn,Sbj,Ent_EN,Ent_CN,FLD_EN,FLD_CN,Fwd_Chk_SQL,Rev_Chk_SQL,Fwd_Chk_Rslt,Rev_Chk_Rslt,Chk_Aim)VALUES(‘‘‘||v_date||‘‘‘,‘‘‘||RS_LOOP.Chk_Big_Cls||‘‘‘,‘‘‘||RS_LOOP.Ordr_Num||‘‘‘,‘‘‘||RS_LOOP.Data_Prtn||‘‘‘,‘‘‘||RS_LOOP.Sbj||‘‘‘,‘‘‘||RS_LOOP.Ent_EN||‘‘‘,‘‘‘||RS_LOOP.Ent_CN||‘‘‘,‘‘‘||RS_LOOP.FLD_EN||‘‘‘,‘‘‘||RS_LOOP.FLD_CN||‘‘‘,‘‘‘||RS_LOOP.Fwd_Chk_SQL||‘‘‘,‘‘‘||RS_LOOP.Rev_Chk_SQL||‘‘‘,‘‘‘||VAL_FWD||‘‘‘,‘‘‘||VAL_REV||‘‘‘,‘‘‘||RS_LOOP.Chk_Aim||‘‘‘)‘;
PREPARE RS_STMT_INST FROM v_sql_insert;
EXECUTE RS_STMT_INST;
END FOR;
END P1
问题:使用ibm data studio 调试发现所有的变量都能正常取出来但是整合到v_sql_insert变量中时就会被截断,v_sql_insert这个变量值出来的不是完整的语句。
尝试的方法:1.最后不使用v_sql_insert这个动态sql ,直接这么写:INSERT INTO RKDM_DATA_VOID_CHK_REST(DATA_DT,Chk_Big_Cls,Ordr_Num,Data_Prtn,Sbj,Ent_EN,Ent_CN,FLD_EN,FLD_CN,Fwd_Chk_SQL,Rev_Chk_SQL,Fwd_Chk_Rslt,Rev_Chk_Rslt,Chk_Aim)VALUES(v_date,RS_LOOP.Chk_Big_Cls,RS_LOOP.Ordr_Num,RS_LOOP.Data_Prtn,RS_LOOP.Sbj,RS_LOOP.Ent_EN,RS_LOOP.Ent_CN,RS_LOOP.FLD_EN,RS_LOOP.FLD_CN,RS_LOOP.Fwd_Chk_SQL,RS_LOOP.Rev_Chk_SQL,VAL_FWD,VAL_REV,RS_LOOP.Chk_Aim)这样做是没有问题。
2.建立页比较大的系统临时表空间。
3.修改v_sql_insert这个变量声明的数据类型大小。
以上是关于存储过程变量中存储SQL语句被截断的问题的主要内容,如果未能解决你的问题,请参考以下文章