2016-09-14 41 views
2

我们可以扫描表并找到数据类型,因为当我们使用导入导出向导它默认甚至是数字列VARCHAR加载csv文件到表中,我们可以导入后扫描表并找到数据类型可能是理想的?扫描和查找数据类型

例如,考虑一个CSV文件A.csv它包含

ColumnA ColumnB ColumnC ColumnD ColumnE 
1234  xyz  123.4 1  abc123 
4258  acv  785.6 0  abs58 
785  fgf  879.6 1  ftrd15 
448  wsd 87878.6 0  wewe 
78528  ews 6968.2 1  awaq 
525554 qwe  2.3 0  afgd87 

所以当我加载此使用导入导出向导的所有列是VARCHAR,但我需要扫描表,然后找到的数据类型。我不关心加载数据的正确数据类型,我最初只关心将数据加载到表中,然后扫描表以找到数据类型。

+2

SSMS数据导入向导可以建议的数据类型(建议 类型按钮),但要小心,因为它有一些限制,并在某个时候做出奇怪的假设。 – ajeh

+0

这与后负荷工作到底如何?一旦你知道这种类型 - 做另一张桌子会怎么办? – Hogan

+0

是使用正确的数据类型创建一个新表 – Zack

回答

2

看起来你会处理的6分主要的数据类型。

  1. DATETIME
  2. INTEGER
  3. DECIMAL
  4. CHARACTER
  5. VARCHAR
  6. BIT

所以一个这样做没有explici方式TLY想每一个转换,赶上一个错误,因为你不能在2008年使用TRY_CONVERT,是利用ISDATE, ISNUMERICCHARINDEX。对于每一列,你可以做这样的事情。当然,你可以在每个列的游标中执行此操作,或者仅复制case语句几次,或者使用交叉连接。

SELECT DISTINCT 
'ColumnA' as ColumnName, 
CASE 
    WHEN ISNUMERIC(ColumnA) = 1 AND LEN(ColumnA) = 1 AND ColumnA NOT LIKE '%[2-9]%' THEN 'Bit', 
    WHEN ISNUMERIC(ColumnA) = 1 AND CHARINDEX('.',ColumnA) > 0 THEN 'Decimal' 
    WHEN ISNUMERIC(ColumnA) = 1 AND CHARINDEX('.',ColumnA) = 0 THEN 'Integer' 
    WHEN ISDATE(ColumnA) = 1 THEN 'Date' 
    WHEN LEN(ColumnA) = 1 AND ColumnA LIKE '%[a-z]%' THEN 'Character' 
    ELSE 'VARCHAR' 
END AS DataTypeCheck 
FROM YourTable 

这并不完美,因为我们没有检查所有的数据类型,但至少应该让你开始。你可以添加一些更LEN()功能找出你想要设置你的DECIMAL长度和精度,以及你VARCHAR()长什么。但是,无法知道插入后续操作是否会导致二进制数据被截断......因为值是未知的。所以你只需要设置这些字段长度足够大,以接受任何后续输入。此外,这将为您提供该列所有可能的数据类型。所以如果你有12和12.34,它将返回INTDECIMAL,其中你应该选择DECIMAL。如果需要,这可以在后续查询中处理。

+0

非常感谢你的回复,这有助于我的事业很多最后一个问题如何确定一个布尔列? – Zack

+0

@Zack你使用'BIT'可以是'0,1或NULL'。我将此添加到案例陈述的第一行。 – scsimon

-2

根据你想要多少个不同的数据类型的支持,您可以使用convert()功能的组合与datalength()发现哪些列可以被成功地转化,并找出正确的数据类型看的成功转换率记录与总数。

但我还是建议装车到避免浪费时间和存储资源,正如我在前面的评论之前发现的类型。

+0

我认为如果它是一次(不是由问题清楚),您可以执行'SELECT cast(columna as integer)FROM table'并查看它是否会更容易报告错误。 – Hogan

+0

是的,如果它是一次性的,并且数据集很小......我们没有完整的OP要求。然后有这整个蠕虫被称为“脏数据”。 – ajeh

+2

低估年。 :D – Hogan

1

这个问题是非常有问题的。数据的目标/预期用途决定了数据类型,而不是数据的不完整扫描。 要确定数据类型是什么,不容易出错代码(以及任何代码容易出错)。例如,如果数据类型是什么20122010

  1. INT/BIGINT
  2. FLOAT
  3. VARCHAR(1 - 8000)
  4. VARBINARY(1 - 8000)
  5. DATE/DATETIME? (它是YYYYDDMMDDMMYYYY?)

什么12ab

  1. VARCHAR(1 - 8000)
  2. VARBINARY(1 - 8000)

什么true

  1. VARCHAR(1 - 8000)

而且依赖于ISNUMERIC是不可靠的,因为它对于不会转换值返回1。例如,在某些文化中,使用逗号代替十进制的句点,因此以下是有效的货币数量,但它不会按照人们预期的方式转换:

SELECT ISNUMERIC('212012,00'); -- 1 
SELECT CONVERT(MONEY, '212012,95') AS [Money]; -- 21201295.00 

或者,如果使用公认的答案代码,以下将被视为一个有效的“整数”:

SELECT CONVERT(INT, '212012,00') AS [Int]; -- error 
-- Msg 245, Level 16, State 1, Line 3 
-- Conversion failed when converting the varchar value '212012,00' to data type int. 

这个怎么样:

SELECT ISNUMERIC('212,012.00,0,1'); -- 1 
+0

逗号的编码很容易。不知道你为什么强调这么多。大家都说OP不应该这样去做。我甚至说它并不完美。感谢您的重复与例子。他们是很好的例子 – scsimon

+0

@scsimon源文件是一个CSV文件,所以也许“数字”不会嵌入逗号,这会消除一些复杂性。尽管如此,我还以为还有其他“奇怪的”ISNUMERIC行为,这使得它不可靠,超出了逗号。但我没有强调这一点。我举了几个例子,其中类型_不能根据值来确定。任何解决方案的工作都有太多的含糊之处。我知道你说这是一个好的开始,并不完美。问题不在于你的解决方案,而在于要求。它使_no_感觉ETLing数据到系统中而不知道它是什么。 –