首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何检查INSERT中哪些列的数据类型不正确?

如何检查INSERT中哪些列的数据类型不正确?
EN

Stack Overflow用户
提问于 2018-04-15 11:47:28
回答 2查看 172关注 0票数 0

假设我在一条INSERT语句中有200列,并且偶尔会收到其中一列的"Cannot convert“错误。问题是,我不知道哪个列导致了这个错误。

在T-SQL或mybatis中有没有办法检查哪一列的格式不正确?(我只有日期、字符、数字)。我可以对每一列使用ISNUMERICISDATE,但这并不是很优雅。

我在Java中使用的是mybatis,所以我不能使用任何PreparedStatement

EN

回答 2

Stack Overflow用户

发布于 2018-04-15 18:46:09

您可以构建一个尝试转换每个可疑列的查询。

并将查询限制到其中一个转换尝试失败的地方。

当尝试将坏数据转换或转换为datetime或number类型时,大多数情况下,坏数据将在CHAR或VARCHAR中。

所以你可以把你的研究局限在这些方面。

此外,从错误中,您应该可以看到哪个值未能转换为哪种类型。这也有助于限制你研究的领域。

使用表变量的简化示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
declare @T1 table (id int identity(1,1) primary key, field1 varchar(30), field2 varchar(30), field3 varchar(30));
declare @T2 table (id int identity(1,1) primary key, field1_int int, field2_date date, field3_dec decimal(10,2));

insert into @T1 (field1, field2, field3) values
('1','2018-01-01','1.23'),
('not an int','2018-01-01','1.23'),
('1','not a date','1.23'),
('1','2018-01-01','not a decimal'),
(null,'2018-01-01','1.23'),
('1',null,'1.23'),
('1','2018-01-01',null)
;

select top 1000
id,
case when try_convert(int, field1) is null then field1 end as field1,
case when try_convert(date, field2) is null then field2 end as field2,
case when try_convert(decimal(10,4), field3) is null then field3 end as field3
from @T1
where 
   try_convert(int, coalesce(field1, '0')) is null
or try_convert(date, coalesce(field2, '1900-01-01')) is null
or try_convert(decimal(10,4), coalesce(field3, '0.0')) is null;

返回:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
id  field1      field2       field3
--  ----------  -----------  -------------
2   not an int  NULL         NULL
3   NULL        not a date   NULL
4   NULL        NULL         not a decimal

如果原始数据不需要太多坏数据,您可以先尝试修复原始数据。

或者对包含错误数据的有问题的列使用try_convert。

例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
insert into @T2 (field1_int, field2_date, field3_dec)
select 
try_convert(int, field1),
try_convert(date, field2),
try_convert(decimal(10,4), field3)
from @T1; 
票数 1
EN

Stack Overflow用户

发布于 2018-04-16 08:43:24

对于较大的导入-特别是当您预计会出现问题时-强烈建议使用两步法。

将数据导入到一个容错能力很强的临时表中(所有NVARCHAR(MAX))

  • check,都会评估、操作、更正所需的数据,并从此处执行真正的

这是一种通用的方法,您可以根据自己的需要进行调整。它将根据类型映射表检查所有表值并输出所有值,这些值在TRY_CAST中失败(需要SQL-Server 2012+)

一个模拟临时表的表(部分借用自LukStorms的answer - thx!)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE #T1 (id INT IDENTITY(1,1) PRIMARY KEY
                 ,fldInt VARCHAR(30)
                 ,fldDate VARCHAR(30)
                 ,fldDecimal VARCHAR(30));
GO

INSERT INTO #T1 (fldInt, fldDate, fldDecimal) values
('1','2018-01-01','1.23'),
('blah','2018-01-01','1.23'),
('1','blah','1.23'),
('1','2018-01-01','blah'),
(null,'2018-01-01','1.23'),
('1',null,'1.23'),
('1','2018-01-01',null);

--类型映射(可能自动从现有目标表的INFORMATION_SCHEMA中获取)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DECLARE @type_map TABLE(ColumnName VARCHAR(100),ColumnType VARCHAR(100));
INSERT INTO @type_map VALUES('fldInt','int')
                           ,('fldDate','date')
                           ,('fldDecimal','decimal(10,2)');

--临时表的名称

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DECLARE @TableName NVARCHAR(100)='#T1'; 

--为每列动态创建的语句

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DECLARE @columnSelect NVARCHAR(MAX)=
(SELECT
    ' UNION ALL SELECT id ,''' +  tm.ColumnName + ''',''' +  tm.ColumnType + ''',' +  QUOTENAME(tm.ColumnName) 
               + ',CASE WHEN TRY_CAST(' + QUOTENAME(tm.ColumnName) + ' AS ' +  tm.ColumnType + ') IS NULL THEN 0 ELSE 1 END ' +
               'FROM ' + QUOTENAME(@TableName)
 FROM @type_map AS tm
 FOR XML PATH('')
);

-The最终动态创建的语句

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DECLARE @cmd NVARCHAR(MAX)=
'SELECT tbl.*
FROM
(
    SELECT 0 AS id,'''' AS ColumnName,'''' AS ColumnType,'''' AS ColumnValue,0 AS IsValid WHERE 1=0 '
  + @columnSelect +
') AS tbl
WHERE tbl.IsValid = 0;'

--使用EXEC()执行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
EXEC(@cmd);

结果是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+----+------------+---------------+-------------+---------+
| id | ColumnName | ColumnType    | ColumnValue | IsValid |
+----+------------+---------------+-------------+---------+
| 2  | fldInt     | int           | blah        | 0       |
+----+------------+---------------+-------------+---------+
| 5  | fldInt     | int           | NULL        | 0       |
+----+------------+---------------+-------------+---------+
| 3  | fldDate    | date          | blah        | 0       |
+----+------------+---------------+-------------+---------+
| 6  | fldDate    | date          | NULL        | 0       |
+----+------------+---------------+-------------+---------+
| 4  | fldDecimal | decimal(10,2) | blah        | 0       |
+----+------------+---------------+-------------+---------+
| 7  | fldDecimal | decimal(10,2) | NULL        | 0       |
+----+------------+---------------+-------------+---------+

创建的语句如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT tbl.*
FROM
(
    SELECT 0 AS id,'' AS ColumnName,'' AS ColumnType,'' AS ColumnValue,0 AS IsValid WHERE 1=0 
    UNION ALL SELECT id 
                    ,'fldInt'
                    ,'int'
                    ,[fldInt]
                    ,CASE WHEN TRY_CAST([fldInt] AS int) IS NULL THEN 0 ELSE 1 END 
              FROM [#T1]
    UNION ALL SELECT id 
                    ,'fldDate'
                    ,'date',[fldDate]
                    ,CASE WHEN TRY_CAST([fldDate] AS date) IS NULL THEN 0 ELSE 1 END 
              FROM [#T1]
    UNION ALL SELECT id 
                   ,'fldDecimal'
                   ,'decimal(10,2)'
                   ,[fldDecimal]
                   ,CASE WHEN TRY_CAST([fldDecimal] AS decimal(10,2)) IS NULL THEN 0 ELSE 1 END 
              FROM [#T1]
) AS tbl
WHERE tbl.IsValid = 0;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49841546

复制
相关文章
C++:43---派生类向基类转换、静态/动态的类变量
一、继承中类的类型转换规则 我们普通的编程规则规定,如果我们想把引用或指针绑定到一个对象上,则引用或指针的类型必须与所绑定的对象的类型一致或者对象的类型含有一种可接受的const类型转换规则。但是继承关系中的类比较例外,其规则如下: ①我们可以将基类的指针或引用绑定到派生对象上 #include <iostream>class A {};class B:public A{};int main(){ A *a; B b; a = &b; return 0;} ②即使不是指针/引用类型,我们也可以将派生类转换为
用户3479834
2021/02/03
1.8K0
C++:43---派生类向基类转换、静态/动态的类变量
scala(十一) 派生类与派生对象
Scala语言是完全面向对象的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,该对象为单例对象。若单例对象名与类名一致,则称该单例对象这个类的伴生对象,这个类的所有“静态”内容都可以放置在它的伴生对象中声明。
用户1483438
2022/04/15
5250
CWnd的派生类-3、CDialog类
对话框与普通窗口的区别仅在于,对话框是通过对话框模板建立起来的。只需要一个以模板为实参的创建命令,如CDialog::Create(),就可以完成对话框窗口及其子控件的创建工作,所有创建细节都由对话框模板来指示。而对于普通窗口,窗口及其包含的子控件必须逐一创建,而且要指定窗口风格等详细参数。对话框是最基本的可视化编程方法,一个应用程序往往包含众多的对话框资源模板和封装类,而普通窗体(包括框架窗体)却寥寥无几。但对话框的使用,只是方便了窗体和控件的创建过程,其本质与普通窗体无任何区别。
全栈程序员站长
2022/07/05
1.3K0
基类和派生类
  在面向对象设计中,被定义为包含所有实体共性的class类型,被称为“基类”。-百度百科
全栈程序员站长
2022/09/20
1K0
派生类的构造过程
1、先基类、后对象、再子类 多继承,初始化顺序跟基类的声明顺序有关,从左到右。 对象 ,与声明类的顺序有关,从上到下。
我与梦想有个约会
2023/10/20
1440
派生类的构造过程
C++中类,对象,封装,继承(派生),多态
类就是同一类事物的总称,比如我(一个对象)可以讲话,那么基本上所有人都具备这个属性,就将我这一类的对象称为类,类的思想就是这样产生的。更恰当的描述:类就是世间事物的抽象称呼,而对象就是这个事物相对应的实体,人类就是一个类,写博文的我,看博文的你就是人类这个类的实例化,这也是为什么人类里面有个类,动物类,植物类,都有一个类,单说一个动物类,我们只能知道是动物,,却无法确定是那种动物,而对象就是具体实例化动物。在C++语言中,类中对象的行为是以函数(方法)的形式定义的,对象的属性是以成员变量的形式定义的,而类包括对象的属性和函数。
花狗Fdog
2022/01/11
1.1K0
C++中类,对象,封装,继承(派生),多态
C++ 类的继承与派生
本文探讨了C++类的继承与派生,介绍了不同的继承方式,包括公有继承、私有继承和保护继承,并说明了C++中类的多态性。同时,文章还介绍了一种在派生类中访问基类成员的方法,即使用作用域解析运算符“.”。此外,文章还介绍了C++中的虚函数和纯虚函数,并说明了C++中的接口和抽象类。
chaibubble
2018/01/02
1.1K0
从TypeScript的类中派生接口[每日前端夜话0xAE]
大多数面向对象编程语言都鼓励编程到接口【https://tuhrig.de/programming-to-an-interface/】的模式。TypeScript 当然支持这一点,你可以创建一个或多个接口,然后再定义生成这个接口实例的类(或工厂)。
疯狂的技术宅
2019/08/23
8470
从TypeScript的类中派生接口[每日前端夜话0xAE]
继承、派生、新式类与经典类
Downwards is the only way forwards .——《盗梦空间》
GH
2019/12/12
5730
类与对象,类的继承,类的派生,类的组合,多态
在python中先有类再有对象,类和对象,你可以看成,类是把对象的相同特征和相同方法汇总再一起,再根据类来生成对象,这个对象具有类的特征与方法
小小咸鱼YwY
2019/07/24
1.2K0
Python使用元类约束派生类中必须实现指定的成员
创建派生类时指定元类,用来控制和约束派生类的创建过程,对派生类中的成员进行一定的限制。
Python小屋屋主
2021/12/29
9830
Python使用元类约束派生类中必须实现指定的成员
Python中类变量、成员变量、局部变量的区别
class A:v1 = 100 # 类变量def __init__(self):self.v2 = 200 # 成员变量v3 = 300 # 局部变量类变量可以由类名统一修改:A.v1 = 300# 则每一个A实例里v1都变成300成员变量只能由实例自己改变:A.v2 # 这个是错的。a = A()a.v2 # 这个是可以访问的。局部变量只在函数内部生效
狼啸风云
2020/10/16
4.4K0
基类派生类多态虚函数?
通常在层次关系的根部有一个基类,其他类则直接或间接的从基类继承而来,这些继承得到的类称为派生类。基类负责定义在层次关系中所有类共同拥有的成员,而每个派生类定义各自特有的成员。
洁洁
2023/10/10
1970
c++-基类与派生类
友元函数必须在类中进行声明而在类外定义,声明时须在函数返回类型前面加上关键字friend。友元函数虽不是类的成员函数,但它可以访问类中的私有和保护类型数据成员。
kdyonly
2023/03/03
3930
java中类变量和实例变量的实质区别
相对于static(静态的)或说类的, 本章开始提到的都是instance(实例的)或说对象的。 每个对象都有自己的一份儿对象域或实例域,相互之间没关系, 不共享。 我们可以从对象中访问实例变量。
马克java社区
2021/03/15
2K0
java中类变量和实例变量的实质区别
虚拟变量在模型中的作用
实际场景中,有很多现象不能单纯的进行定量描述,只能用例如“出现”“不出现”这样的形式进行描述,这种情况下就需要引入虚拟变量。例如即将到来的女生节,每年的这个时候毛绒玩具的销量都会上升,说明女生节对毛绒玩具的销量产生了一定影响,但是这个影响程度又很难界定,这时只能定义一个虚拟变量去描述事情“发生”与“不发生”了。
许卉
2019/07/15
4.3K0
解决cpp添加QObject派生类的问题
一般我们继承QObject类在头文件中添加,但是有时候需要在源文件中添加。这样就会不可避免地出现编译错误。那么我们该究竟怎么解决它呢? 问题重现 执行下列源码会报以下错误: error: undefined reference to `vtable for Object' 错误: 未定义引用'Object'的虚函数表 问题源码: /* main.cpp */ #include <QCoreApplication> class Object : public QObject { Q_OBJECT p
Qt君
2019/07/15
1.8K0
C++继承和派生练习(一)--关于从people(人员)类派生出student(学生)类等
从people(人员)类派生出student(学生)类 添加属性:班号char classNO[7];从people类派生出teacher(教师)类, 添加属性:职务char principalship[11]、部门char department[21]。 从student类中派生graduate(研究生)类,添加属性:专业char subject[21]、 导师char teacher_adviser[21];从graduate类和teacher类派生出TA(助教生)类, 注意
Enterprise_
2019/03/01
1K0
C++继承和派生练习(一)--关于从people(人员)类派生出student(学生)类等
C++继承和派生练习(一)--关于从people(人员)类派生出student(学生)类等
从people(人员)类派生出student(学生)类 添加属性:班号char classNO[7];从people类派生出teacher(教师)类, 添加属性:职务char principalship[11]、部门char department[21]。 从student类中派生graduate(研究生)类,添加属性:专业char subject[21]、 导师char teacher_adviser[21];从graduate类和teacher类派生出TA(助教生)类, 注意虚基类
Enterprise_
2018/05/18
2.6K0
c++继承 基类 派生类 虚函数
类和类的关系有组合、继承和代理。继承的本质就是代码复用。子类继承父类中的一些东西,父类也称为基类,子类也称为派生类。派生类继承了基类除构造函数以外的所有成员。
用户7886150
2021/02/03
1.1K0

相似问题

UCanAccess调用保存的追加、更新或删除查询

10

TLA+中序列元素和集合元素的比较

10

尾递归调用尾递归

24

Kotlin -A函数被标记为尾递归,但没有发现尾调用。

27

如何实现尾递归列表追加?

31
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文