مقدمة في وظائف خادم SQL وفوائدها وعيوبها
ما هي وظيفة SQL؟
يمكن استخدام وظائف SQL Server لإرجاع إما قيم أو جداول مفردة ، باستخدام إجراءات T-SQL أو CLR (وقت تشغيل اللغة العامة) وإجراء عمليات حسابية أكثر تعقيدًا مما قد ترغب في استخدامه في التعليمات البرمجية العامة.
متى يكون استخدام دالة بدلاً من التعليمات البرمجية المضمنة فكرة جيدة؟
إستخدام جيد
يمكن استخدام الوظائف لاستبدال طرق العرض (إرجاع جدول) ، كعمود محسوب في جدول ، أو تنفيذ إجراءات بحث متسقة أو لمجرد تعديل التعليمات البرمجية التي يمكن أن تساعد في تقليل التغييرات المطلوبة.
استخدام سيء
نراه طوال الوقت ، ولكن لا ينبغي استخدام الوظائف لإرجاع بيانات البحث بدلاً من الصلة عندما تتعامل مع مجموعات بيانات كبيرة. سيستدعي كل صف نفس الوظيفة حتى لو واجه هذه القيمة بالفعل. في هذه الحالات ، استخدم صلة.
أمثلة على وظيفة قشارة
تُستخدم وظائف Scaler بشكل أفضل لأداء المنطق مثل إعادة التنسيق أو الحسابات المستندة إلى الصفوف حيث يتم استدعاؤها حسب طبيعتها لكل صف ، ويمكن استخدامها للبحث عن البيانات في جدول آخر ، ولكن بشكل عام ، ستحصل على أداء أفضل باستخدام صلة. لهذا ، يمكننا إلقاء نظرة على وظيفة الحصول على العمر على الرابط التالي.
إن تخزين عمر شخص ما في الوقت الذي يملأ فيه نموذجًا لن يكون له معنى ، لأنه عندما يتم الاستعلام عن البيانات لاحقًا ، ستكون قديمة. سيكون الخيار الأفضل هو التقاط تاريخ الميلاد وحسابه بسرعة. في وظيفتنا أضفنا حقلاً حتى ، والذي يمكن استخدامه لتأريخ عملية حسابية ، أو ربما بطريقة أكثر حزنًا ، لحساب العمر وقت الوفاة (تم تمديد هذه الوظيفة لعقد NHS).
Example
CREATE FUNCTION [Dates].[GetAge](@Date DATETIME2,@Until DATETIME2) RETURNS INT AS BEGINIF @Until IS NULL SET @Until=CONVERT(DATE,GETDATE())DECLARE @Age INT=DATEDIFF(YEAR,@Date,@Until)+(CASE WHEN DATEPART(DAYOFYEAR,@Date)>(DATEPART(DAYOFYEAR,@Until)+(CASE WHEN dbo.GetLeapYear(@Date)=1 AND DATEPART(DAYOFYEAR,@Date)>59 THEN 1 ELSE 0 END))THEN -1 ELSE 0 END)RETURN @AgeEND
أمثلة على وظيفة قشارة
لاستخدام هذا من جدول خيالي ، سنستخدم هذا ببساطة ، والذي سيوفر إما العمر الحالي أو العمر عند الوفاة.
Use in a select statement
SELECT [PersonID],[DateOfBirth],[dbo].[GetAge]([DateOfBirth],[DeceasedDate]) AgeAsFunction,--Simpler code to understand!DATEDIFF(YEAR,[DateOfBirth],[DeceasedDate])+(CASE WHEN DATEPART(DAYOFYEAR,[DateOfBirth])>(DATEPART(DAYOFYEAR,[DeceasedDate])+(CASE WHEN dbo.GetLeapYear([DateOfBirth])=1 AND DATEPART(DAYOFYEAR,[DateOfBirth])>59 THEN 1 ELSE 0 END))THEN -1 ELSE 0 END) AgeAsScript,[DeceasedDate]FROM [Person]
أمثلة على وظيفة قشارة
المزايا : متسقة ، معيارية ، أكثر إحكاما ، من المحتمل أن تقلل من عدد التغييرات
العيوب : لرؤية الكود تحتاج للبحث في الوظيفة
في حين أن هذه الوظيفة مفيدة بشكل عام ، إلا أنها دقيقة للغاية أيضًا ، لأنها تستخدم وظيفة السنة الكبيسة. إنها غير حتمية بطبيعتها ، لذا لا ينبغي أبدًا تخزينها كبيانات مستمرة.
أمثلة عمود الجدول
يمكن إضافة الأعمدة المحسوبة على أنها إما مستمرة (تتغير عند البيانات) أو غير مستمرة (يتم حسابها في كل مرة يتم فيها تحديد الصف). يمكننا إلقاء نظرة على طريقتين استخدمناها هنا في نظام إدارة المحتوى الخاص بنا.
ملاحظة : قد يكون من الصعب تحقيق البيانات المستمرة لأنها تتطلب مجموعة من القيود التي يجب الوفاء بها
غير مستمر: العمر
باستخدام وظيفة العمر كما هو مذكور أعلاه ، يمكننا إضافة هذا إلى جدول وتمرير القيم من الأعمدة الأخرى. ثم نختاره ببساطة كعمود.
Add to a table
CREATE TABLE [Person]([PersonID] [int] IDENTITY(1,1) NOT NULL,[DateOfBirth] [datetime] NULL,[Age] AS ([dbo].[GetAge]([DateOfBirth],[DeceasedDate])),[DeceasedDate] [datetime] NULL)
Select Statement
SELECT [PersonID],[DateOfBirth],[Age] AgeAsColumn,--Even simpler code to understand!DATEDIFF(YEAR,[DateOfBirth],[DeceasedDate])+(CASE WHEN DATEPART(DAYOFYEAR,[DateOfBirth])>(DATEPART(DAYOFYEAR,[DeceasedDate])+(CASE WHEN dbo.GetLeapYear([DateOfBirth])=1 AND DATEPART(DAYOFYEAR,[DateOfBirth])>59 THEN 1 ELSE 0 END))THEN -1 ELSE 0 END) AgeAsScript,[DeceasedDate]FROM [Person]
غير مستمر: العمر
المزايا : ثابت ، معياري
العيوب : يبطئ سرعة الاستعلام إذا لم يكن هناك حاجة لذلك.
استمر: مصغر CSS
لدينا وظيفة تقلل المساحة المطلوبة لـ CSS بنسبة تصل إلى 30٪. سيؤدي استدعاء هذا بانتظام إلى إبطاء سرعة تحديد الجدول ، ونظرًا لأن البيانات نادرًا ما يتم تحديثها ، فمن المنطقي إجراء العمليات الحسابية في وقت الإدراج / التحديث. من خلال إنشاء العمود كوظيفة ، لا نحتاج إلى إجراء هذه العمليات كمحفز أيضًا.
Add to a Table
CREATE TABLE CSS(CSSID INT IDENTITY(1,1) NOT NULL,CSSText NVARCHAR(MAX),CSSMin AS (ous.CSSProcessor([CSSText])) PERSISTED)
استمر: مصغر CSS
يمكن تحديده تمامًا مثل العمود العادي ، ويتم تخزين البيانات في الجدول. كما أنه يتجنب استخدام عبارة استبدال ضخمة تؤدي إلى تضخيم الكود الخاص بنا.
المزايا : سرعة تحديد متسقة ، معيارية ، أسرع ، لا حاجة لمشغل!
العيوب : يزيد المساحة اللازمة للجدول ، ويبطئ سرعة الإدخال
استبدال وجهة نظر
نميل إلى عدم استخدام طرق العرض ، باستثناء الوقت الذي نستخدم فيه نفس الصلات بانتظام في أماكن متعددة.
حتى في هذه الحالات ، لا يوجد سبب يمنع استخدام دالة الجدول بشكل أكثر فعالية. يمكن العثور على الجدول الذي استخدمناه على الرابط أدناه ، ولدينا مثالين على الاستخدام ، أحدهما عبر وظيفة والآخر باستخدام طريقة عرض.
Create a function
CREATE FUNCTION Dates.GetCalender(@DateFrom DATETIME2,@DateTo DATETIME2,@Function INT) RETURNS @D TABLE (CalenderDate DATETIME2(7) NOT NULL PRIMARY KEY,CalenderCA INT NULL,CalenderCD INT NULL,WeekDayID INT NULL,WeekDayName VARCHAR(9) NULL,HolidayType NVARCHAR(100)) AS BEGININSERT INTO @DSELECT c.*,HolidayTypeFROM [Utilities].[Dates].[Calender] cLEFT JOIN Utilities.Dates.CalenderHolidays h ON h.CalenderDate=c.CalenderDate AND CalenderFunction=@FunctionWHERE c.CalenderDate BETWEEN @DateFrom AND @DateTo RETURNENDGO
Create a view
CREATE VIEW Dates.GetCalenderView ASSELECT c.CalenderDate, CalenderCA, CalenderCD, WeekDayID, WeekDayName,h.HolidayType,c.CalenderFunctionFROM (SELECT CalenderDate, CalenderCA, CalenderCD, WeekDayID, WeekDayName, CalenderFunction FROM [Utilities].[Dates].[Calender],(SELECT DISTINCT CalenderFunction FROM Dates.CalenderHolidays) x) cLEFT JOIN Utilities.Dates.CalenderHolidays h ON h.CalenderDate=c.CalenderDate AND h.CalenderFunction=c.CalenderFunction
Usage
SELECT * FROM Dates.GetCalender('2018-01-01','2018-12-31',0) --England & WalesSELECT * FROM Dates.GetCalender('2018-01-01','2018-12-31',1) --Scotland----OR----SELECT * FROM Dates.GetCalenderView WHERE CalenderDate BETWEEN '2018-01-01' AND '2018-12-31' AND CalenderFunction=0
استبدال وجهة نظر
الفوائد : ضغط للاتصال ، يتم إرجاعه باستخدام المفتاح الأساسي (مثالي للانضمام الإضافي) ، يمكن استخدام المعلمات مسبقًا في الكود.
العيوب : المزيد من التعليمات البرمجية للبناء ، أقل مرونة
استخدم في تطبيق الصلات
تعد وظائف الجدول رائعة لاستخدامها في تطبيق الصلات ، حيث يمكن تمرير البيانات على أساس صف بصف. نحن نستخدم وظيفة TextToRows الخاصة بنا لفصل السلاسل في SQL Server. في المثال أدناه ، نستخدم تطبيقًا مزدوجًا لتقسيم البيانات مرتين باستخدام محددات مختلفة.
SQL Code
DECLARE @TestText TABLE(TextToSplit NVARCHAR(100))INSERT INTO @TestText SELECT 'Text,To,Tows:Split,One'INSERT INTO @TestText SELECT 'Text,To,Tows:Split,Two'SELECT t.TextToSplit,s1.WordInt,s1.WordStr,s2.WordInt,s2.WordStrFROM @TestText tOUTER APPLY dbo.TextToRows(':',TextToSplit) s1OUTER APPLY dbo.TextToRows(',',WordStr) s2
Further detail
Some of the functions we have written can be found below.