سؤال

إذا قمت بإعداد عمود جدول ليكون عمدا محسوبا يتم استدعاء صيادته وظيفة، يصبح الألم لتغيير هذه الوظيفة الأساسية. مع كل تغيير، عليك أن تجد كل عمود واحد تشير صيادته التي تشير إلى الوظيفة، وإزالة المرجع، وحفظ الجدول، وتغيير الوظيفة، وإضافة كل شيء مرة أخرى، واحفظ مرة أخرى. حتى التغييرات الصغيرة هي كوابيس.

هل يمكن أن تخبر SQL Server أنك لا تهتم بأن الوظيفة تتم الإشارة إليها بواسطة الصيغ والمضي قدما وتغيير الوظيفة الأساسية؟

التفاصيل الإضافية: لا يستمر العمود المحسوب أو تمت الإشارة إليه بواسطة قيود FK لأنه غير محدد. تأخذ الوظيفة في الاعتبار الوقت الحالي. إنه يتعامل مع مسألة ما إذا كان سجل منتهي الصلاحية أم لا.

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

المحلول

لا، بقدر ما أعرف، لا يمكنك القيام بذلك - عليك أولا إزالة جميع الأعمدة المحسوبة التي تشير إلى وظيفة، وتغيير الوظيفة، ثم إعادة إنشاء الأعمدة المحسوبة.

ربما MS سوف تعطينا أمر "إنشاء أو تغيير وظيفة" في SQL Server 2010/2011؟ :-)

مارك

نصائح أخرى

عواقب التغيير قد تكون ضخمة.

هل قمت بفهرسة الأعمدة؟ تستخدمه في عرض مع مخطط؟ استمر في ذلك؟ العلاقة الرئيسية الأجنبية مع ذلك؟

ماذا لو تغير التغيير نوع البيانات أو التبانة أو الحتمية؟

من الأسهل إيقاف تشغيل الوظيفة بالتبعية من التعامل مع العديد من السيناريوهات.

آسف لهذا الإجابة المتأخرة، ولكن يمكن أن تكون مفيدة.

يمكنك استخدام وظيفة وهمية لكل عمود محسوب سيتصل بظائفك الحقيقية.

مثال:
العمود المحسوب يستخدم الصيغة: dbo.link_comp ('123')
هذه الوظيفة إعادة توجيه الحجج والمكالمات وإرجاع الوظيفة dbo.link ('123') (وظيفتك الحقيقية)
كلا الوظائف تحتاج فقط إلى استخدام نفس الحجج وإرجاع نفس النوع.

ثم، فإن الوظيفة التي تم تأمينها هي dbo.link_comp ويمكنك تغيير dbo.link.
أيضا، إذا تم استدعاء دئتك من SQL الأخرى، فلا يزال بإمكانك استخدام اسم الدالة الحقيقي الخاص بك dbo.link، فهي دالة الدمية dbo.link_comp هي فقط للعمود المحسوب.

يفترض الجدول T1 مع الأعمدة C1، C2، C3، C4، C5 حيث C4 هو عمود محسوب

افترض أيضا وظيفة المراجع C4 OldFunc التي تريد استبدالها بواسطة NewFunc

أولا، نقل الأعمدة غير المحسوبة من جميع الصفوف إلى جدول TEMP

Select C1, C2, C3, C5 into TmpT1 from T1
Go

بعد ذلك، احذف جميع الصفوف من T1

Delete From T1
go

الآن يمكنك تعديل العمود C4

Alter table T1 alter column C4 as dbo.NewFunc()
Go

ضع الآن البيانات المحفوظة مرة أخرى في الجدول الأصلي

Insert Into T1 (C1,C2,C3,C5) select C1,C2,C3,C5 from TmpT1

الآن حذف جدول TEMP

Drop Table TmpT1

يمكنك محاولة مع بعض أدوات مخطط جيدة مقارنة، والتي تنشئ البرنامج النصي لك :)

يمكنك تغيير العمود ليتم حسابه، وتحديثه عن طريق الزناد.

أو يمكنك إعادة تسمية الجدول إلى شيء آخر، وقم بإسقاط العمود المحسوب، وإنشاء طريقة عرض في مكان الجدول الأصلي (أي مع اسم الجدول الأصلي) و بما في ذلك العمود "المحسوب" الذي تحتاجه.

تحرير: لاحظ أن هذا قد يفسد مع إدراجك في اسم الجدول الأصلي (الآن عرض). من الواضح أنك يمكن أن تبقي الجدول القديم، وإسقاط العمود المحسوب، وإنشاء طريقة عرض منفصلة تحتوي على العمود المحسوب.

لقد اضطررنا إلى العمل حول الأعمدة المحسوبة أوقات كافية لقررها أنها مشكلة أكثر مما ربح. FAIL-SAF إدراج (1)، في محاولة لإدراج طرق العرض على الجداول مع الأعمدة المحسوبة، والأشياء التي تتطلب العبث مع تعيين Arithabort وهلم جرا.

(1) لدينا إدراج الفشل الآمن مثل:

إدراج في اختيار mytable * من myothertable حيث ...

التي تم تصميمها للفشل إذا تمت إضافة عمود جديد جدول واحد وليس الآخر. مع العمود المحسوب، يتعين علينا تسمية جميع الأعمدة بشكل صريح، مما يفقدنا أن شبكة الأمان.

أعلم أن هذا متأخرا على الحفلة، لكنني كنت أحصل على هذه المشكلة نفسها اليوم ولم أجد أي شيء يحل المشكلة بالفعل، لذلك سرعان ما أخرجت واحدة.

في الأساس، يقوم بإنشاء جدول مؤقت يحمل معلومات الأعمدة لكل عمود محسوب باستخدام الوظيفة، يسقط الأعمدة من الجداول. يمكنك بعد ذلك تحديث وظيفتك واتركها إعادة إنشاء جميع الأعمدة مرة أخرى بتعاريفها.

إذا كان عليك إجراء تغييرات على المعلمات ضمن التعريفات (كما أحتاج إلى)، فيمكنك ببساطة البرنامج النصي هذا الجزء إلى حيث يتم إنشاء التعريفات مرة أخرى.

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

آمل أن تكون مفيدة لشخص آخر.

/* Create temporary table to hold definitions */
CREATE TABLE [#FUNCTION]
(
    [TABLE_NAME] nvarchar(255) NOT NULL,
    [COLUMN_NAME] nvarchar(255) NOT NULL,
    [DEFINITION] nvarchar(255) NOT NULL
)
GO

/* Add data to temp table */
INSERT INTO [#FUNCTION] ( [TABLE_NAME], [COLUMN_NAME], [DEFINITION] )
SELECT TABLE_NAME, COLUMN_NAME, definition FROM INFORMATION_SCHEMA.COLUMNS
INNER JOIN sys.computed_columns ON ( object_id = object_id( TABLE_NAME ) AND name = COLUMN_NAME )
WHERE definition LIKE '%MyFunctionName%'
GO

/* Remove columns */
DECLARE @TABLE_NAME nvarchar(255)
DECLARE @COLUMN_NAME nvarchar(255)

DECLARE c_CursorName CURSOR LOCAL FOR SELECT [TABLE_NAME], [COLUMN_NAME] FROM [#FUNCTION]
OPEN c_CursorName

FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC( 'ALTER TABLE [' + @TABLE_NAME + '] DROP COLUMN [' + @COLUMN_NAME + ']' )

    FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME
END

CLOSE c_CursorName
DEALLOCATE c_CursorName
GO

/* Update function */
-- Update function here
GO

/* Recreate computed columns */
DECLARE @TABLE_NAME nvarchar(255)
DECLARE @COLUMN_NAME nvarchar(255)
DECLARE @DEFINITION nvarchar(255)

DECLARE c_CursorName CURSOR LOCAL FOR SELECT [TABLE_NAME], [COLUMN_NAME], [DEFINITION] FROM [#FUNCTION]
OPEN c_CursorName

FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME, @DEFINITION

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC( 'ALTER TABLE [' + @TABLE_NAME + '] ADD [' + @COLUMN_NAME + '] AS ' + @DEFINITION )

    FETCH NEXT FROM c_CursorName INTO @TABLE_NAME, @COLUMN_NAME, @DEFINITION
END

CLOSE c_CursorName
DEALLOCATE c_CursorName
GO

/* Remove temp table */
DROP TABLE [#FUNCTION]
GO
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top