كيفية التحقق مما إذا كان هناك قيود في SQL Server؟
-
21-09-2019 - |
سؤال
لدي هذا 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]
نظرًا لأن الجدول قد يحتوي على مفاتيح أجنبية متعددة وما زال لا يتم فحص المفتاح الخارجي