[英]How to find out whether a table has some unique columns
我使用MS SQL Server。
我已經交了一些沒有約束的大桌子,沒有鑰匙也沒有。
我知道有些列具有唯一值。 對於給定的表,是否有一種聰明的方法來查找具有唯一值的cols?
現在,我通過計算是否存在與表中的行一樣多的DISTINCT值來手動為每列執行此操作。
SELECT COUNT(DISTINCT col) FROM table
可能會讓一個cusor循環遍歷所有列,但想聽聽是否有人知道更聰明或內置函數。
謝謝。
這是一種基本類似於@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(DISTINCT column)
與每列的COUNT(*)
進行比較。 結果將是一個包含單行的表,其中每列將包含不具有重復項的列的值UNIQUE
,如果存在重復項,則為空字符串。
但上述解決方案僅適用於那些沒有NULL的列。 應該注意,當您要在列上創建唯一約束/索引時,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);
此解決方案通過檢查三個值來考慮NULL: COUNT(DISTINCT column)
, COUNT(column)
和COUNT(*)
。 它顯示的結果與前一種解決方案類似,但列的可能診斷更加多樣化:
UNIQUE
表示沒有重復值且沒有NULL(可以是PK或具有唯一約束/索引);
UNIQUE WITH SINGLE NULL
- 可以猜到,沒有重復,但是有一個NULL(不能是PK,但可以有唯一的約束/索引);
UNIQUE with NULLs
- 沒有重復項,兩個或多個NULL(如果你在SQL Server 2008上,你可以只有非NULL值的條件唯一索引);
空字符串 - 有重復項,也可能是NULL。
我想這可能是最干凈的方式。 只需使用動態sql和單個select語句來創建一個查詢,該查詢為每個字段提供總行數和不同值的計數。
在頂部填寫數據庫名稱和表名。 數據庫名稱部分非常重要,因為OBJECT_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
如果您使用的是2008,則可以使用SSIS中的數據概要分析任務返回每個表的候選密鑰。
這篇博客文章介紹了這個過程,它非常簡單:
我的代碼做了幾句話:
讀取所有表格和列
創建臨時表以保存具有重復鍵的表/列
對於每個表/列,它運行查詢。 如果它為至少一個值找到count(*)> 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
簡單的一行代碼怎么樣:
CREATE UNIQUE INDEX index_name ON table_name (column_name);
如果創建了索引,則column_name僅具有唯一值。 如果column_name中存在欺騙,則會收到錯誤消息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.