在下面的代码中,我将值插入表中并获取错误"字符串或二进制数据将被截断。"
我的表格定义:
CREATE TABLE urs_prem_feed_out_control
(
bd_pr_cntl_rec_type char(7) NULL ,
pd_pr_cntl_acctg_dte char(6) NULL ,
bd_pr_cntl_run_dte char(10) NULL ,
bd_pr_cntl_start_dte char(10) NULL ,
bd_pr_cntl_end_dte char(10) NULL ,
bd_pr_cntl_rec_count char(16) NULL ,
bd_pr_tot_premium char(16) NULL ,
bd_pr_tot_commission char(16) NULL ,
fd_ctl_nbr integer NOT NULL
)
DECLARE @cur_fd_ctl_nbr INT = 2,
@acctg_cyc_ym_2 CHAR(6) = '201402',
@rundate CHAR (10) = CONVERT(CHAR(10),GETDATE(),101),
@cycle_start_dt DATETIME = '2014-02-17',
@cycle_end_dt DATETIME = '2014-02-24',
@record_count INT = 24704,
@tot_pr_premium DECIMAL(18,2) = 476922242,
@tot_pr_comm DECIMAL(18,2) = 2624209257
插入代码(我已将变量声明为测试的常量值,我从运行时的值中获取这些值):
INSERT INTO urs_prem_feed_out_control
SELECT fd_ctl_nbr = @cur_fd_ctl_nbr,
bd_pr_cntl_rec_type = 'CONTROL',
bd_pr_cntl_acctg_dte = @acctg_cyc_ym_2,
bd_pr_cntl_run_dte = @rundate,
bd_pr_cntl_start_dte = CONVERT(CHAR(10),@cycle_start_dt,101),
bd_pr_cntl_end_dte = CONVERT(CHAR(10),@cycle_end_dt,101),
bd_pr_cntl_rec_count = RIGHT('0000000000000000' + RTRIM(CONVERT(CHAR(16),@record_count)),16),
bd_pr_tot_premium = CASE
WHEN @tot_pr_premium < 0
THEN '-' + SUBSTRING(RIGHT('000000000000000' + LTRIM(RTRIM(CONVERT(VARCHAR,ABS(@tot_pr_premium)*100))),18),1,15)
ELSE
'+' + SUBSTRING(RIGHT('000000000000000' + LTRIM(RTRIM(CONVERT(VARCHAR,ABS(@tot_pr_premium)*100))),18),1,15)
END,
bd_pr_tot_commission = CASE
WHEN @tot_pr_comm < 0
THEN '-' + SUBSTRING(RIGHT('000000000000000' + LTRIM(RTRIM(CONVERT(VARCHAR,ABS(@tot_pr_comm)*100))),18),1,15)
ELSE
'+' + SUBSTRING(RIGHT('000000000000000' + LTRIM(RTRIM(CONVERT(VARCHAR,ABS(@tot_pr_comm)*100))),18),1,15)
END
当我单独查看每个值时,似乎它们都在表的可变长度约束内。知道为什么我会收到这个错误吗?
谢谢!
答案 0 :(得分:4)
插入查询的问题是插入顺序:
SELECT fd_ctl_nbr = @cur_fd_ctl_nbr,
此列必须在INSERT
中的最后一列定义为create table脚本中定义的最后一列。
将您的查询更改为:
INSERT INTO #urs_prem_feed_out_control (fd_ctl_nbr, bd_pr_cntl_rec_type, pd_pr_cntl_acctg_dte, bd_pr_cntl_run_dte, bd_pr_cntl_start_dte, bd_pr_cntl_end_dte, bd_pr_cntl_rec_count, bd_pr_tot_premium, bd_pr_tot_commission)
SELECT fd_ctl_nbr = @cur_fd_ctl_nbr,
bd_pr_cntl_rec_type = 'CONTROL',
bd_pr_cntl_acctg_dte = @acctg_cyc_ym_2,
bd_pr_cntl_run_dte = @rundate,
bd_pr_cntl_start_dte = CONVERT(CHAR(10),@cycle_start_dt,101),
bd_pr_cntl_end_dte = CONVERT(CHAR(10),@cycle_end_dt,101),
bd_pr_cntl_rec_count = RIGHT('0000000000000000' + RTRIM(CONVERT(CHAR(16),@record_count)),16),
bd_pr_tot_premium = CASE
WHEN @tot_pr_premium < 0
THEN '-' + SUBSTRING(RIGHT('000000000000000' + LTRIM(RTRIM(CONVERT(VARCHAR,ABS(@tot_pr_premium)*100))),18),1,15)
ELSE
'+' + SUBSTRING(RIGHT('000000000000000' + LTRIM(RTRIM(CONVERT(VARCHAR,ABS(@tot_pr_premium)*100))),18),1,15)
END,
bd_pr_tot_commission = CASE
WHEN @tot_pr_comm < 0
THEN '-' + SUBSTRING(RIGHT('000000000000000' + LTRIM(RTRIM(CONVERT(VARCHAR,ABS(@tot_pr_comm)*100))),18),1,15)
ELSE
'+' + SUBSTRING(RIGHT('000000000000000' + LTRIM(RTRIM(CONVERT(VARCHAR,ABS(@tot_pr_comm)*100))),18),1,15)
END
这样做也行得通。请注意,SELECT
中INSERT
中的第一列就是您在问题中提供的方式。
在此处查看 - &gt; http://sqlfiddle.com/#!3/0e09b/1
希望这有帮助!!!
答案 1 :(得分:2)
这就是为什么你不应该在没有指定列的情况下编写insert语句。既然你没有,它会尝试按照它们在表格中的顺序将数据放入列中,这完全不是你所拥有的顺序。
当你得到这种消息时可能发生的另一件事(但我不认为适用于你的情况,我将其包含在以后搜索的人中)是因为eeror实际上是来自触发器,而不是主要的插入。
最后关于数据库设计的说明,你不应该使用char作为日期,你应该使用日期字段。你不能在char字段上做日期数学,它会接受不正确的日期值,如feb30,2014。将日期存储为除日期或日期时间值之外的任何内容总是一个坏主意。通常,只有当列总是具有相同数量的字符(如2列状态缩写)时,才应该很少使用char,它不应该用作默认数据类型。您需要更好地定义与存储数据的类型和大小相匹配的数据类型。您可能会遇到查询问题,因为'VA'与'VA'不同。一般来说,我的经验是不到1%的数据库字段应该是Char。
答案 2 :(得分:1)
我认为仔细检查你的工作可能是有益的。请考虑以下示例代码:
DECLARE @Table TABLE (Name NVARCHAR(1))
INSERT INTO @Table (Name) SELECT 'ab'
INSERT INTO @Table (Name) SELECT SUBSTRING('ab',1,2)
INSERT INTO @Table (Name) SELECT RIGHT('abc',2)
所有产生以下结果:字符串或二进制数据将被截断。