سؤال

لدي هذا SQL:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

ولكن على ما يبدو ، في بعض قواعد البيانات الأخرى التي نستخدمها ، يكون للقيد اسم مختلف. كيف أتحقق مما إذا كان هناك قيد مع الاسم FK_ChannelPlayerSkins_Channels.

هل كانت مفيدة؟

المحلول

جرب هذا:

SELECT
    * 
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS 
    WHERE CONSTRAINT_NAME ='FK_ChannelPlayerSkins_Channels'

-- تعديل --

عندما أجبت في الأصل على هذا السؤال ، كنت أفكر في "مفتاح خارجي" لأن السؤال الأصلي طرح حول العثور على "fk_channelplayerskins_channels". منذ ذلك الحين ، علق الكثير من الناس على العثور على "قيود" أخرى فيما يلي بعض الاستفسارات الأخرى لذلك:

--Returns one row for each CHECK, UNIQUE, PRIMARY KEY, and/or FOREIGN KEY
SELECT * 
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
    WHERE CONSTRAINT_NAME='XYZ'  


--Returns one row for each FOREIGN KEY constrain
SELECT * 
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS 
    WHERE CONSTRAINT_NAME='XYZ'


--Returns one row for each CHECK constraint 
SELECT * 
    FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS
    WHERE CONSTRAINT_NAME='XYZ'

هذه طريقة بديلة

--Returns 1 row for each CHECK, UNIQUE, PRIMARY KEY, FOREIGN KEY, and/or DEFAULT
SELECT 
    OBJECT_NAME(OBJECT_ID) AS NameofConstraint
        ,SCHEMA_NAME(schema_id) AS SchemaName
        ,OBJECT_NAME(parent_object_id) AS TableName
        ,type_desc AS ConstraintType
    FROM sys.objects
    WHERE type_desc LIKE '%CONSTRAINT'
        AND OBJECT_NAME(OBJECT_ID)='XYZ'

إذا كنت بحاجة إلى مزيد من معلومات القيد ، فابحث داخل الإجراء المخزن النظام master.sys.sp_helpconstraint لمعرفة كيفية الحصول على معلومات معينة. لعرض الكود المصدري باستخدام SQL Server Management Studio ، احصل على "Explorer". من هناك تقوم بتوسيع قاعدة البيانات "الرئيسية" ، ثم توسيع "قابلية البرمجة" ، ثم "الإجراءات المخزنة" ، ثم "الإجراءات المخزنة للنظام". يمكنك بعد ذلك العثور على "sys.sp_helpconstraint" ونقره الأيمن وتحديد "تعديل". فقط احرص على عدم حفظ أي تغييرات عليها. أيضًا ، يمكنك فقط استخدام هذا الإجراء المخزن النظام على أي جدول باستخدامه مثل EXEC sp_helpconstraint YourTableNameHere.

نصائح أخرى

أسهل طريقة للتحقق من وجود قيد (ثم القيام بشيء مثل إسقاطه إذا كان موجودًا) هو استخدام وظيفة Object_id () ...

IF OBJECT_ID('dbo.[CK_ConstraintName]', 'C') IS NOT NULL 
    ALTER TABLE dbo.[tablename] DROP CONSTRAINT CK_ConstraintName

يمكن استخدام Object_id بدون المعلمة الثانية ("C" للتحقق من قيود فقط) وقد يعمل ذلك أيضًا ، ولكن إذا كان اسم القيد الخاص بك يطابق اسم الكائنات الأخرى في قاعدة البيانات ، فقد تحصل على نتائج غير متوقعة.

IF OBJECT_ID('dbo.[CK_ConstraintName]') IS NOT NULL 
    ALTER TABLE dbo.[tablename] DROP CONSTRAINT CK_ConstraintName

يمكن أيضًا استخدام Object_id مع "قيود" أخرى مثل قيود المفاتيح الخارجية أو قيود المفاتيح الأساسية ، وما إلى ذلك للحصول على أفضل النتائج ، قم دائمًا بتضمين نوع الكائن المناسب كمعلمة ثانية لوظيفة Object_ID:

أنواع كائنات القيد:

  • ج = التحقق من القيد
  • D = الافتراضي (القيد أو المستقلة)
  • F = قيود المفتاح الخارجي
  • PK = قيود المفتاح الأساسي
  • ص = القاعدة (النمط القديم ، مستقلة)
  • UQ = قيد فريد

لاحظ أيضًا أن المخطط مطلوب غالبًا. مخطط القيود بشكل عام يأخذ مخطط الجدول الأصل.

قد يتسبب الفشل في وضع قيودك (أو أي شيء تقوم بفحصه) في قوسين عند استخدام هذه الطريقة أيضًا إلى سلبية خاطئة - إذا كان كائنك يستخدم أحرفًا غير عادية (مثل A.) ، فإن الأقواس مطلوبة.

إذا كنت تبحث عن نوع آخر من القيد ، على سبيل المثال ، يجب عليك استخدام استعلام مختلف (من كيف أجد قيودًا افتراضية باستخدام معلومات _schema؟ أجاب من قبل ديفيو). يستخدم:

SELECT * FROM sys.objects WHERE type = 'D' AND name = @name

للعثور على قيود افتراضية بالاسم.

لقد جمعت معًا "إذا لم تكن موجودة"ddl 'إذا لم تكن موجودة "ظروف لجعل البرامج النصية SQL إعادة تشغيل"

IF (OBJECT_ID('FK_ChannelPlayerSkins_Channels') IS NOT NULL)

هل تنظر إلى شيء مثل هذا ، يتم اختبار أدناه في SQL Server 2005

SELECT * FROM sys.check_constraints WHERE 
object_id = OBJECT_ID(N'[dbo].[CK_accounts]') AND 
parent_object_id = OBJECT_ID(N'[dbo]. [accounts]')

مجرد شيء يجب الانتباه إليه ......

في SQL Server 2008 R2 SSMS ، فإن أمر "Script As -> Drop and Create to" ينتج T -SQL كما هو موضح أدناه

USE [MyDatabase]
GO

IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DEF_Detail_IsDeleted]') AND type = 'D')
BEGIN
ALTER TABLE [Patient].[Detail] DROP CONSTRAINT [DEF_Detail_IsDeleted]
END

GO

USE [MyDatabase]
GO

ALTER TABLE [Patient].[Detail] ADD  CONSTRAINT [DEF_Detail_IsDeleted]  DEFAULT ((0)) FOR [IsDeleted]
GO

خارج المربع ، لا يسقط هذا البرنامج النصي القيد لأن تحديد صفوف 0. (انظر الوظيفة Microsoft Connect).

اسم القيد الافتراضي خاطئ ، لكنني أجمعه أيضًا له علاقة بوظيفة Object_id لأن تغيير الاسم لا يحدد المشكلة.

لإصلاح ذلك ، أزلت استخدام Object_id واستخدمت اسم القيد الافتراضي بدلاً من ذلك.

(SELECT * FROM dbo.sysobjects WHERE [name] = (N'DEF_Detail_IsDeleted') AND type = 'D')

يمكنني استخدام الاستعلام التالي للتحقق من وجود قيد موجود قبل إنشائه.

IF (NOT EXISTS(SELECT 1 FROM sysconstraints WHERE OBJECT_NAME(constid) = 'UX_CONSTRAINT_NAME' AND OBJECT_NAME(id) = 'TABLE_NAME')) BEGIN
...
END

هذا الاستعلامات للقيد بالاسم الذي يستهدف اسم جدول معين. أتمنى أن يساعدك هذا.

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.TableName'))
 BEGIN 
ALTER TABLE TableName DROP CONSTRAINT CONSTRAINTNAME 
END 
IF EXISTS(SELECT TOP 1 1 FROM sys.default_constraints WHERE parent_object_id = OBJECT_ID(N'[dbo].[ChannelPlayerSkins]') AND name = 'FK_ChannelPlayerSkins_Channels')
BEGIN
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels
END
GO

INFORMATION_SCHEMA هو صديقك. يحتوي على جميع أنواع المشاهدات التي تظهر جميع أنواع معلومات المخطط. تحقق من طرق عرض النظام الخاصة بك. ستجد أن لديك ثلاث وجهات نظر تتعامل مع القيود ، واحدة كائن CHECK_CONSTRAINTS.

أستخدم هذا للتحقق من القيود عن بُعد والقيود عن بُعد على عمود. يجب أن يكون كل ما تحتاجه.

DECLARE
  @ps_TableName VARCHAR(300)
  , @ps_ColumnName VARCHAR(300)

SET @ps_TableName = 'mytable'
SET @ps_ColumnName = 'mycolumn'

DECLARE c_ConsList CURSOR LOCAL STATIC FORWARD_ONLY FOR
    SELECT
    'ALTER TABLE ' + RTRIM(tb.name) + ' drop constraint ' + sco.name AS csql
    FROM
        sys.Objects tb
        INNER JOIN sys.Columns tc on (tb.Object_id = tc.object_id)
        INNER JOIN sys.sysconstraints sc ON (tc.Object_ID = sc.id and tc.column_id = sc.colid)
        INNER JOIN sys.objects sco ON (sc.Constid = sco.object_id)
    where
        tb.name=@ps_TableName
        AND tc.name=@ps_ColumnName
OPEN c_ConsList
FETCH c_ConsList INTO @ls_SQL
WHILE (@@FETCH_STATUS = 0) BEGIN

    IF RTRIM(ISNULL(@ls_SQL, '')) <> '' BEGIN
        EXECUTE(@ls_SQL)
    END
    FETCH c_ConsList INTO @ls_SQL
END
CLOSE c_ConsList
DEALLOCATE c_ConsList
SELECT tabla.name as Tabla,

        restriccion.name as Restriccion, 
        restriccion.type as Tipo, 
        restriccion.type_desc as Tipo_Desc
FROM {DATABASE_NAME}.sys.objects tabla 

INNER JOIN {DATABASE_NAME}.sys.objects restriccion

ON tabla.object_id = restriccion.parent_object_id

WHERE tabla.type = 'U' - Solo tablas creadas por el usuario.

AND restriccion.type = 'UQ' --Tipo de Restriccion UNIQUE

ORDER BY tabla.name, restriccion.type_desc                

يمكنك استخدام واحد أعلاه مع تحذير واحد:

IF EXISTS(
    SELECT 1 FROM sys.foreign_keys 
    WHERE parent_object_id = OBJECT_ID(N'dbo.TableName') 
        AND name = 'CONSTRAINTNAME'
)
BEGIN 
    ALTER TABLE TableName DROP CONSTRAINT CONSTRAINTNAME 
END 

تحتاج إلى استخدام name = [Constraint name] نظرًا لأن الجدول قد يحتوي على مفاتيح أجنبية متعددة وما زال لا يتم فحص المفتاح الخارجي

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top