คุณจะพิจารณาได้อย่างไรว่าตาราง SQL ใดมีคอลัมน์ข้อมูลประจำตัวโดยทางโปรแกรม


103

ฉันต้องการสร้างรายการคอลัมน์ใน SQL Server 2005 ที่มีคอลัมน์ข้อมูลประจำตัวและตารางที่เกี่ยวข้องใน T-SQL

ผลลัพธ์จะเป็นดังนี้:

TableName, ColumnName

คำตอบ:


174

อีกวิธีหนึ่งที่เป็นไปได้ในการดำเนินการนี้สำหรับ SQL Server ซึ่งมีการพึ่งพาตารางระบบน้อยกว่า (ซึ่งอาจมีการเปลี่ยนแปลงเวอร์ชันเป็นเวอร์ชัน) คือการใช้มุมมอง INFORMATION_SCHEMA:

select COLUMN_NAME, TABLE_NAME
from INFORMATION_SCHEMA.COLUMNS
where COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
order by TABLE_NAME 

โปรดทราบว่า gotcha คือคุณสามารถระบุ [db name] .information_schema.columns แต่เรียกใช้จากฐานข้อมูลอื่น ... จากนั้น COLUMNPROPERTY กำลังทำงานกับฐานข้อมูลที่ไม่ถูกต้อง
Mike M

12
วิธีนี้จะดีกว่าเมื่อคุณมีสคีมาอื่น ๆ : โดยที่ COLUMNPROPERTY (object_id (TABLE_SCHEMA + '.' + TABLE_NAME) ...
Hossein Margani

1
ฉันคิดว่าคำตอบนี้ใช้ไม่ได้กับ Microsoft SQL Server 2014
ChrisW

หากคุณกำลังมองหาแนวทางง่ายๆที่ใช้งานได้จาก SQL Server 2000 เป็นต้นไปให้ดูที่คำตอบนี้โดย @Guillermo
Lankymart

INFORMATION_SCHEMA.COLUMNSมีข้อมูลสำหรับตารางธรรมดาและมุมมองและฉันขอแนะนำให้เพิ่ม TABLE_TYPE (เข้าร่วม INFORMATION_SCHEMA.TABLES) เพื่อให้สามารถอ่านชุดผลลัพธ์ได้
Diego Scaravaggi

51

sys.columns.is_identity = 1

เช่น,

select o.name, c.name
from sys.objects o inner join sys.columns c on o.object_id = c.object_id
where c.is_identity = 1

2
หมายเหตุ: สิ่งนี้ใช้ได้กับฉันใน SQL 2008 ในขณะที่คำตอบที่ยอมรับใช้ไม่ได้ (คำถามถามหา SQL 2005)
Daniel Schaffer

1
คำตอบนี้ใช้ได้กับ Microsoft SQL Server 2014 ด้วย
ChrisW

27

อีกวิธีหนึ่ง (สำหรับปี 2000/2005/2012/2014):

IF ((SELECT OBJECTPROPERTY( OBJECT_ID(N'table_name_here'), 'TableHasIdentity')) = 1)
    PRINT 'Yes'
ELSE
    PRINT 'No'

หมายเหตุ: table_name_hereควรจะเว้นแต่คีมาคือschema.tabledbo



3

คำถามนี้ดูเหมือนจะทำเคล็ดลับ:

SELECT 
    sys.objects.name AS table_name, 
    sys.columns.name AS column_name
FROM sys.columns JOIN sys.objects 
    ON sys.columns.object_id=sys.objects.object_id
WHERE 
    sys.columns.is_identity=1
    AND
    sys.objects.type in (N'U')

2

นี่คือเวอร์ชันที่ใช้งานได้สำหรับ MSSQL 2000 ฉันได้แก้ไขโค้ดปี 2005 แล้วที่นี่: http://sqlfool.com/2011/01/identity-columns-are-you-nearing-the-limits/

/* Define how close we are to the value limit
   before we start throwing up the red flag.
   The higher the value, the closer to the limit. */
DECLARE @threshold DECIMAL(3,2);
SET @threshold = .85;

/* Create a temp table */
CREATE TABLE #identityStatus
(
      database_name     VARCHAR(128)
    , table_name        VARCHAR(128)
    , column_name       VARCHAR(128)
    , data_type         VARCHAR(128)
    , last_value        BIGINT
    , max_value         BIGINT
);

DECLARE @dbname sysname;
DECLARE @sql nvarchar(4000);

-- Use an cursor to iterate through the databases since in 2000 there's no sp_MSForEachDB command...

DECLARE c cursor FAST_FORWARD FOR
SELECT
    name
FROM
    master.dbo.sysdatabases 
WHERE 
    name NOT IN('master', 'model', 'msdb', 'tempdb');

OPEN c;

FETCH NEXT FROM c INTO @dbname;

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sql = N'Use [' + @dbname + '];
    Insert Into #identityStatus
    Select ''' + @dbname + ''' As [database_name]
        , Object_Name(id.id) As [table_name]
        , id.name As [column_name]
        , t.name As [data_type]
        , IDENT_CURRENT(Object_Name(id.id)) As [last_value]
        , Case 
            When t.name = ''tinyint''   Then 255 
            When t.name = ''smallint''  Then 32767 
            When t.name = ''int''       Then 2147483647 
            When t.name = ''bigint''    Then 9223372036854775807
          End As [max_value]
    From 
        syscolumns As id
        Join systypes As t On id.xtype = t.xtype
    Where 
        id.colstat&1 = 1    -- this identifies the identity columns (as far as I know)
    ';

    EXECUTE sp_executesql @sql;

    FETCH NEXT FROM c INTO @dbname;
END

CLOSE c;
DEALLOCATE c;

/* Retrieve our results and format it all prettily */
SELECT database_name
    , table_name
    , column_name
    , data_type
    , last_value
    , CASE 
        WHEN last_value < 0 THEN 100
        ELSE (1 - CAST(last_value AS FLOAT(4)) / max_value) * 100 
      END AS [percentLeft]
    , CASE 
        WHEN CAST(last_value AS FLOAT(4)) / max_value >= @threshold
            THEN 'warning: approaching max limit'
        ELSE 'okay'
        END AS [id_status]
FROM #identityStatus
ORDER BY percentLeft;

/* Clean up after ourselves */
DROP TABLE #identityStatus;

2

รายการตารางที่ไม่มีคอลัมน์ Identity ตามคำตอบของGuillermo :

SELECT DISTINCT TABLE_NAME
FROM            INFORMATION_SCHEMA.COLUMNS
WHERE        (TABLE_SCHEMA = 'dbo') AND (OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 0)
ORDER BY TABLE_NAME

2

แบบสอบถามต่อไปนี้ใช้ได้ผลสำหรับฉัน:

select  TABLE_NAME tabla,COLUMN_NAME columna
from    INFORMATION_SCHEMA.COLUMNS
where   COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
order by TABLE_NAME

1

ฉันคิดว่าสิ่งนี้ใช้ได้กับ SQL 2000:

SELECT 
    CASE WHEN C.autoval IS NOT NULL THEN
        'Identity'
    ELSE
        'Not Identity'
    AND
FROM
    sysobjects O
INNER JOIN
    syscolumns C
ON
    O.id = C.id
WHERE
    O.NAME = @TableName
AND
    C.NAME = @ColumnName

ฉันไม่รู้ว่า autoval ทำอะไร แต่มันเป็นโมฆะสำหรับช่องข้อมูลประจำตัวทั้งหมดของฉัน รหัส SQL 2000 ที่ฉันมีใช้งานได้คือโดยที่ colstat & 1 = 1 ฉันไม่แน่ใจว่ารหัสนั้นมาจากไหน (อายุประมาณ 5 ปี) แต่ความคิดเห็นของฉันบอกว่าจำเป็นต้องมี bitmask แต่ colstat = 1 สำหรับตัวตนของฉัน
Kevin Crumley

อืม ... ฉันใช้สถานะ & 128 = 128 เพื่อระบุตัวตนของฉัน :-P
Brimstedt

1

สิ่งนี้ใช้ได้กับฉันโดยใช้ Sql Server 2008:

USE <database_name>;
GO
SELECT SCHEMA_NAME(schema_id) AS schema_name
    , t.name AS table_name
    , c.name AS column_name
FROM sys.tables AS t
JOIN sys.identity_columns c ON t.object_id = c.object_id
ORDER BY schema_name, table_name;
GO

1

ใช้สิ่งนี้:

DECLARE @Table_Name VARCHAR(100) 
DECLARE @Column_Name VARCHAR(100)
SET @Table_Name = ''
SET @Column_Name = ''

SELECT  RowNumber = ROW_NUMBER() OVER ( PARTITION BY T.[Name] ORDER BY T.[Name], C.column_id ) ,
    SCHEMA_NAME(T.schema_id) AS SchemaName ,
    T.[Name] AS Table_Name ,
    C.[Name] AS Field_Name ,
    sysType.name ,
    C.max_length ,
    C.is_nullable ,
    C.is_identity ,
    C.scale ,
    C.precision
FROM    Sys.Tables AS T
    LEFT JOIN Sys.Columns AS C ON ( T.[Object_Id] = C.[Object_Id] )
    LEFT JOIN sys.types AS sysType ON ( C.user_type_id = sysType.user_type_id )
WHERE   ( Type = 'U' )
    AND ( C.Name LIKE '%' + @Column_Name + '%' )
    AND ( T.Name LIKE '%' + @Table_Name + '%' )
ORDER BY T.[Name] ,
    C.column_id

1

สิ่งนี้ใช้ได้กับ SQL Server 2005, 2008 และ 2012 ฉันพบว่า sys.identity_columns ไม่มีตารางทั้งหมดของฉันที่มีคอลัมน์ข้อมูลประจำตัว

SELECT a.name AS TableName, b.name AS IdentityColumn
FROM sys.sysobjects a 
JOIN sys.syscolumns b 
ON a.id = b.id
WHERE is_identity = 1
ORDER BY name;

ดูที่หน้าเอกสารประกอบสามารถใช้คอลัมน์สถานะได้ นอกจากนี้คุณสามารถเพิ่มตัวระบุสี่ส่วนและมันจะทำงานในเซิร์ฟเวอร์ต่างๆ

SELECT a.name AS TableName, b.name AS IdentityColumn
FROM [YOUR_SERVER_NAME].[YOUR_DB_NAME].sys.sysobjects a 
JOIN [YOUR_SERVER_NAME].[YOUR_DB_NAME].sys.syscolumns b 
ON a.id = b.id
WHERE is_identity = 1
ORDER BY name;

ที่มา: https://msdn.microsoft.com/en-us/library/ms186816.aspx


1

ด้วยเหตุผลบางประการเซิร์ฟเวอร์ sql บันทึกคอลัมน์ข้อมูลประจำตัวบางคอลัมน์ในตารางต่างกันรหัสที่ใช้ได้กับฉันมีดังต่อไปนี้

select      TABLE_NAME tabla,COLUMN_NAME columna
from        INFORMATION_SCHEMA.COLUMNS
where       COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
union all
select      o.name tabla, c.name columna
from        sys.objects o 
inner join  sys.columns c on o.object_id = c.object_id
where       c.is_identity = 1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.