扫描并查找数据类型

时间:2016-09-14 17:45:50

标签: sql sql-server sql-server-2008

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

例如,考虑它包含的csv文件A.csv

public bool AreEqual(object x, object y, ref Tolerance tolerance)
{
    if (x == null && y == null)
        return true;

    if (x == null || y == null)
        return false;

    if (object.ReferenceEquals(x, y))
        return true;

    // Omitted: a whole bunch of checks for specific types that will fail in your case.

    return x.Equals(y);
}

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

3 个答案:

答案 0 :(得分:2)

看起来您正在处理6种主要数据类型。

  1. DATETIME
  2. INTEGER
  3. DECIMAL
  4. CHARACTER
  5. VARCHAR
  6. BIT
  7. 因此,一种方法是在没有明确尝试转换每一个并捕获错误的情况下执行此操作,因为您在2008年无法使用TRY_CONVERT,而是使用ISDATE, ISNUMERIC和{{1 }}。对于每一列,您可以执行类似的操作。当然,您可以在每个列的游标中执行此操作,或者只是复制case语句几次,或者使用交叉连接。

    CHARINDEX

    它并不完美,因为我们没有检查所有数据类型,但它应该至少让你开始。您可以添加更多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长度。但是,无法知道后续插入是否会导致二进制数据被截断...因为值未知。因此,您只需将这些字段长度设置为足以接受任何后续输入。此外,这将为您提供该列的所有可能的数据类型。因此,如果您有12和12.34,则会返回VARCHAR()INT,您应该选择DECIMAL。如果需要,可以在后续查询中处理。

答案 1 :(得分:1)

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

  1. INT / BIGINT
  2. FLOAT
  3. VARCHAR(1 - 8000)
  4. VARBINARY(1 - 8000)
  5. DATE / DATETIME? (是YYYYDDMM还是DDMMYYYY?)
  6. 12ab

    怎么样?
    1. VARCHAR(1 - 8000)
    2. VARBINARY(1 - 8000)
    3. true

      怎么样?
      1. VARCHAR(1 - 8000)
      2. BIT
      3. 依赖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
        

答案 2 :(得分:-2)

根据您要支持的不同数据类型的数量,您可以使用public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.LowercaseUrls = true; routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } 函数与convert()的组合来发现可以成功转换的列,并找出正确的数据类型查看成功转换记录与总数的百分比。

但我仍然建议在加载之前发现类型,以避免浪费时间和存储资源,正如我之前评论的那样。