Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何确定一个表是否有一些唯一的列_Sql_Sql Server_Unique - Fatal编程技术网

Sql 如何确定一个表是否有一些唯一的列

Sql 如何确定一个表是否有一些唯一的列,sql,sql-server,unique,Sql,Sql Server,Unique,我使用MS SQL Server 有人递给我一些大桌子,没有任何约束,没有钥匙,什么都没有 我知道有些列有唯一的值。对于给定的表,是否有一种智能的方法来查找具有唯一值的COL 现在,我通过计算表中的行数来手动计算每一列的不同值 SELECT COUNT(DISTINCT col) FROM table prob可以制作一个cusor循环遍历所有列,但想知道是否有人知道更智能的或内置的函数 谢谢。如果您使用的是2008,您可以使用SSIS中的数据分析任务为每个表返回候选键 此博客条目将逐步完成整

我使用MS SQL Server

有人递给我一些大桌子,没有任何约束,没有钥匙,什么都没有

我知道有些列有唯一的值。对于给定的表,是否有一种智能的方法来查找具有唯一值的COL

现在,我通过计算表中的行数来手动计算每一列的不同值

SELECT COUNT(DISTINCT col) FROM table
prob可以制作一个cusor循环遍历所有列,但想知道是否有人知道更智能的或内置的函数


谢谢。

如果您使用的是2008,您可以使用SSIS中的数据分析任务为每个表返回候选键

此博客条目将逐步完成整个过程,非常简单:


几句话我的代码的作用:

  • 阅读所有表格和列

  • 创建临时表以保存具有重复键的表/列

  • 对于每个表/列,它运行一个查询。如果它发现至少一个值的计数(*)大于1 它在临时表中插入一个

  • 从与发现重复的表/列不匹配的系统表中选择的列和值

    DECLARE @sql VARCHAR(max)
    DECLARE @table VARCHAR(100)
    DECLARE @column VARCHAR(100)
    
    
    CREATE TABLE #temp (tname VARCHAR(100),cname VARCHAR(100))
    
    DECLARE mycursor CURSOR FOR
    select t.name,c.name
    from sys.tables t
    join sys.columns c on t.object_id = c.object_id
    where system_type_id not in (34,35,99)
    
    OPEN mycursor
    FETCH NEXT FROM mycursor INTO @table,@column
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
    SET @sql = 'INSERT INTO #temp SELECT DISTINCT '''+@table+''','''+@column+ ''' FROM ' + @table + ' GROUP BY ' + @column +' HAVING COUNT(*)>1 '
    EXEC (@sql)
    FETCH NEXT FROM mycursor INTO @table,@column
    END
    
    select t.name,c.name
    from sys.tables t
    join sys.columns c on t.object_id = c.object_id
    left join #temp on t.name = #temp.tname and c.name = #temp.cname
    where system_type_id not in (34,35,99) and #temp.tname IS NULL
    
    DROP TABLE #temp
    
    CLOSE mycursor
    DEALLOCATE mycursor
    

  • 我认为这可能是最干净的方法。只需使用动态sql和单个select语句创建一个查询,该查询为每个字段提供总行数和不同值的计数

    在顶部填写数据库名和表名。DB name部分非常重要,因为
    OBJECT\u name
    仅在当前数据库上下文中有效

    use DatabaseName
    
    DECLARE @Table varchar(100) = 'TableName'
    
    DECLARE @SQL Varchar(max)
    
    SET @SQL = 'SELECT COUNT(*) as ''Total'''
    
    SELECT @SQL = @SQL + ',COUNT(DISTINCT ' + name + ') as ''' + name + ''''
    FROM sys.columns c
    WHERE OBJECT_NAME(object_id) = @Table
    
    SET @SQL = @SQL + ' FROM ' + @Table
    
    exec @sql
    

    这里有一种基本上类似于@JNK的方法,但它不打印计数,而是为每一列返回一个现成的答案,告诉您一列是否只包含唯一的值:

    DECLARE @table varchar(100), @sql varchar(max);
    SET @table = 'some table name';
    
    SELECT
      @sql = COALESCE(@sql + ', ', '') + ColumnExpression
    FROM (
      SELECT
        ColumnExpression =
          'CASE COUNT(DISTINCT ' + COLUMN_NAME + ') ' +
          'WHEN COUNT(*) THEN ''UNIQUE'' ' +
          'ELSE '''' ' +
          'END AS ' + COLUMN_NAME
      FROM INFORMATION_SCHEMA.COLUMNS
      WHERE TABLE_NAME = @table
    ) s
    
    SET @sql = 'SELECT ' + @sql + ' FROM ' + @table;
    PRINT @sql;  /* in case you want to have a look at the resulting query */
    EXEC(@sql);
    
    它只是将每一列的
    COUNT(不同列)
    COUNT(*)
    进行比较。结果将是一个具有单行的表,其中每列都将包含没有重复项的列的值
    UNIQUE
    ,如果存在重复项,则为空字符串

    但上述解决方案仅适用于那些没有空值的列。需要注意的是,当您要在列上创建唯一的约束/索引时,SQL Server不会忽略null。如果一个列只包含一个NULL,而所有其他值都是唯一的,则仍然可以在该列上创建唯一约束(但不能将其作为主键,这需要值的唯一性和不存在NULL)

    因此,您可能需要对内容进行更彻底的分析,您可以通过以下脚本获得:

    DECLARE @table varchar(100), @sql varchar(max);
    SET @table = 'some table name';
    
    SELECT
      @sql = COALESCE(@sql + ', ', '') + ColumnExpression
    FROM (
      SELECT
        ColumnExpression =
          'CASE COUNT(DISTINCT ' + COLUMN_NAME + ') ' +
          'WHEN COUNT(*) THEN ''UNIQUE'' ' +
          'WHEN COUNT(*) - 1 THEN ' +
            'CASE COUNT(DISTINCT ' + COLUMN_NAME + ') ' +
            'WHEN COUNT(' + COLUMN_NAME + ') THEN ''UNIQUE WITH SINGLE NULL'' ' +
            'ELSE '''' ' +
            'END ' +
          'WHEN COUNT(' + COLUMN_NAME + ') THEN ''UNIQUE with NULLs'' ' +
          'ELSE '''' ' +
          'END AS ' + COLUMN_NAME
      FROM INFORMATION_SCHEMA.COLUMNS
      WHERE TABLE_NAME = @table
    ) s
    
    SET @sql = 'SELECT ' + @sql + ' FROM ' + @table;
    PRINT @sql;  /* in case you still want to have a look at the resulting query */
    EXEC(@sql);
    
    此解决方案通过检查三个值来考虑空值:
    COUNT(DISTINCT column)
    COUNT(column)
    COUNT(*)
    。它显示的结果与前一个解决方案类似,但列的可能诊断更加多样化:

    • UNIQUE
      表示没有重复值和空值(可以是PK或具有唯一约束/索引)

    • UNIQUE WITH SINGLE NULL
      –可以猜测,没有重复项,但有一个NULL(不能是PK,但可以有唯一的约束/索引)

    • UNIQUE with NULLs
      –无重复项,两个或多个NULLs(如果您在SQL Server 2008上,您可以仅为非NULL值设置条件唯一索引)

    • 空字符串–存在重复项,也可能为空


      • 简单的一行代码怎么样:

        CREATE UNIQUE INDEX index_name ON table_name (column_name);
        

        如果创建了索引,则列名只有唯一的值。如果列名中有重复项,您将收到一条错误消息。

        如果列中没有空值,这将非常有用。SQL Server在创建唯一约束/索引时会考虑空值。感谢您的回答,我没有尝试过它,因为它运行在所有表上,这不是我在这个特定问题中需要的。您可以在游标查询定义中添加一个附加子句:AND tname=your_table_namegiving error警告:通过聚合或其他集合操作消除空值。“。不能从应用程序使用。@user998660:“从应用程序对警告特别敏感。””“你是说?那样的话,当然不能。不过,并非所有的应用程序都那么敏感。例如,我不记得Delphi中有过产生此类警告的聚合问题。无论如何,我的印象是OP想要一个他们可以“手动”使用的解决方案,例如,在查询的情况下,在SSMS之类的工具中调用它。