Ê×Ò³ ÐÂÎÅ ÂÛ̳ Ⱥ×é Blog Îĵµ ÏÂÔØ ¶ÁÊé Tag ÍøÕª ËÑË÷ ¿ªÔ´ FAQ µÚ¶þÊéµê ²©ÎÄÊӵ㠳ÌÐòÔ±
ƵµÀ: Ñз¢ Êý¾Ý¿â Öмä¼þ ÐÅÏ¢»¯ ÊÓÆµ .NET Java ÓÎÏ· ÒÆ¶¯ ·þÎñ: È˲ŠÍâ°ü Åàѵ
    Í¼Ê鯷ÖÖ£º235680ÖÖ
       
ÈÈÃÅËÑË÷£º ASP.NET Ajax Spring Hibernate Java

6.2  ±êÁ¿UDF

±êÁ¿UDF·µ»Øµ¥¸ö£¨±êÁ¿£©Öµ¡£¿ÉÒÔÔÚÔÊÐíʹÓñêÁ¿±í´ïʽ£¨scalar expression£©µÄµØ·½Ê¹ÓñêÁ¿UDF¡£ÀýÈç²éѯ¡¢Ô¼Êø¡¢¼ÆËãÁеȡ£±êÁ¿UDFÒªÇóÂú×ãÏÂÃæÕ⼸¸öÓï·¨ÒªÇó£º

n  ±ØÐë°üº¬BEGIN/END¿éÒÔ¶¨Ò庯ÊýµÄÖ÷Ìå¡£

n  µ÷ÓÃʱ±ØÐëÏÞ¶¨¼Ü¹¹£¨³ý·ÇÏñ´æ´¢¹ý³Ìµ÷Ò»Ñù±»EXECµ÷Óã¬ÈçEXEC myFunction 3, 4£©¡£

n  µ÷ÓÃʱ²»ÔÊÐíºöÂÔ¿ÉÑ¡²ÎÊý£¨ÓÐĬÈÏÖµµÄ²ÎÊý£©£»»òÕߣ¬ÖÁÉÙΪËüÃÇÖ¸¶¨DEFAULT¹Ø¼ü×Ö¡£

ÏÂÃæ½éÉÜT-SQLºÍCLR UDF¡£

T-SQL±êÁ¿UDF

µ±²Ù×÷µÄÖ÷Òª³É±¾À´×ÔÓÚ»ùÓÚ¼¯ºÏµÄÊý¾Ý²Ù×÷¶ø²»Êǹý³ÌÂß¼­ºÍ¼ÆËãʱ£¬T-SQL UDFͨ³£Òª±ÈCLR UDF¿ì¡£²»½öUDFÊÇÕâÑù£¬ÆäËûÀàÐ͵ijÌÐòÒ²ÊÇÈç´Ë¡£´´½¨UDFʱ£¬ÔÚº¯ÊýÍ·Ö¸¶¨Ãû³Æ¡¢¶¨ÒåÊäÈë²ÎÊý¡¢¶¨Òå·µ»ØÖµµÄÊý¾ÝÀàÐÍ¡£×÷Ϊһ¸ö±êÁ¿UDFµÄʾÀý£¬ÏÂÃæµÄ´úÂë´´½¨fn_ConcatOrdersº¯Êý£¬Ëü½ÓÊÕ¿Í»§ID×÷ΪÊäÈë²¢·µ»Ø´®Áª¸Ã¿Í»§µÄOrderIDµÃµ½µÄ×Ö·û´®¡£

SET NOCOUNT ON;

USE Northwind;

GO

IF OBJECT_ID('dbo.fn_ConcatOrders') IS NOT NULL

  DROP FUNCTION dbo.fn_ConcatOrders;

GO

CREATE FUNCTION dbo.fn_ConcatOrders

  (@cid AS NCHAR(5)) RETURNS VARCHAR(8000)

AS

BEGIN

  DECLARE @orders AS VARCHAR(8000);

  SET @orders = '';

  SELECT @orders = @orders + CAST(OrderID AS VARCHAR(10)) + ';'

  FROM dbo.Orders

  WHERE CustomerID = @cid;

  RETURN @orders;

END

GO

º¯ÊýÏÈÉùÃ÷±äÁ¿ @orders²¢³õʼ»¯Îª¿Õ×Ö·û´®¡£º¯ÊýÖеIJéѯʹÓÃÁËÒ»¸öÌØÊâµÄSELECT¸³ÖµÓï·¨¡£ËüɨÃè·ûºÏÌõ¼þµÄÐУ¬Ã¿Ò»Ðж¼Îª @orders±äÁ¿¸³Öµ¡£¸ÃÖµÊÇͨ¹ý´®Áª×îÐ嵀 @ordersÄÚÈݺ͵±Ç°ÐеÄOrderIDÖµ²¢ÓÃÒ»¸ö·ÖºÅ×÷Ϊ·Ö¸ô·ûµÃµ½µÄ¡£

ÖØÒª    ¸Ã²éѯ²»±£Ö¤´®ÁªµÄ˳Ðò¡£OrderID½«°´SQL ServerɨÃèÊý¾ÝµÄÎïÀí˳Ðò½øÐд®Áª¡£ÔÚÕâÑùµÄ²éѯÖУ¬²»ÒªÒÀÀµORDER BY×Ӿ䡣Èç¹ûÄãÖ¸¶¨ÁËORDER BY×Ӿ䣬SQL Server²»»á²úÉú´íÎ󣬵«Ëü²»±£Ö¤ÔÚ¸³ÖµÇ°¶ÔÊý¾ÝÅÅÐò¡£
ͬÑù£¬Î¢ÈíҲûÓÐÕýʽµÄÎĵµÃèÊö¾ÛºÏ´®Áª£¨aggregate concatenation£©¼¼Êõ£¨ÎÞÂÛÊÇ·ñʹÓÃORDER BY×Ӿ䣩¡£ÕâÀïËùÃèÊöµÄÐÐΪ½ö½öÊÇ»ùÓÚ¹Û²ìµÃµ½µÄ£¬ÎÒ»¹Î´·¢ÏÖ²»Ê¹ÓÃORDER BYʱ»áʧ°Ü¡£µ«Òª¼Çס£¬¹Ù·½²»±£Ö¤ËµËùÓзûºÏÌõ¼þÐеÄÔªËØ¶¼»á±»´®Áª£¬ËùÒÔÄã×îºÃ±ÜÃâÔÚ²úÆ·´úÂëÖÐÍêÈ«ÒÀÀµÕâÏî¼¼Êõ¡£

Òª²âÊÔfn_ConcatOrdersº¯Êý£¬ÔËÐÐÏÂÃæµÄ²éѯ£¬ËüÉú³ÉµÄÊä³öÒÔ¼ò»¯ÐÎʽÏÔʾÔÚ±í6-1ÖС£

SELECT CustomerID, dbo.fn_ConcatOrders(CustomerID) AS Orders

FROM dbo.Customers;

±í6-1  ÎªÃ¿¸ö¿Í»§´®Áª¶©µ¥ID¸öµÃµ½µÄ½á¹û(±»¼ò»¯)

CustomerID

Orders

ALFKI

10643;10692;10702;10835;10952;11011;

ANATR

10308;10625;10759;10926;

ANTON

10365;10507;10535;10573;10677;10682;10856;

AROUT

10355;10383;10453;10558;10707;

10741;10743;10768;10793;10864;10920; 10953;11016;

BERGS

10278;10280;10384;10444;10445;10524;10572;10626;

10654;10672;10689;10733;10778;10837;

10857;10866;10875;10924;

BLAUS

10501;10509;10582;10614;10853;10956;11058;

BLONP

10265;10297;10360;10436;10449;

10559;10566;10584;10628;10679;10826;

BOLID

10326;10801;10970;

BONAP

10331;10340;10362;10470;10511;10525;10663;10715;

10730;10732;10755;10827;10871;10876;10932;10940;11076;

BSBEV

10289;10471;10484;10538;

10539;10578;10599;10943;10947;11023;

¡­

¡­

ÔÚSQL Server 2005ÖУ¬Äã²»±ØÔÙʹÓÃÕâÖÖ·½·¨ÊµÏÖ×Ö·û´®´®Áª¡£Äã¿ÉÒÔʹÓÃFOR XML PATHÑ¡Ï²¢ÓÃÒ»¸ö¿Õ×Ö·û´®×÷ΪÆäÊäÈ룬¾ÍÏñÕâÑù£º

SET NOCOUNT ON;

USE Northwind;

GO

SELECT CustomerID,

  (SELECT CAST(OrderID AS VARCHAR(10)) + ';' AS [text()]

   FROM dbo.Orders AS O

   WHERE O.CustomerID = C.CustomerID

   ORDER BY OrderID

   FOR XML PATH('')) AS Orders

FROM dbo.Customers AS C;

ÕâÑùÄã¾Í¿ÉÒÔÍêÈ«¿ØÖÆ´®ÁªµÄ˳ÐòÁË¡£

ÔÚSQL Server 2005ÖÐʹÓÃÓû§¶¨Òå¾ÛºÏº¯Êý£¨UDA£©Ò²¿ÉÒÔ½â¾öÕâ¸öÎÊÌâ¡£µ«Ê¹ÓÃUDAÄ㽫ÎÞ·¨¿ØÖÆ´®ÁªµÄ˳Ðò£¬ÇÒ´®ÁªµÄ×Ö·û´®±»ÏÞÖÆÎª8000¸ö×Ö½Ú¡£¹ØÓÚUDAµÄ¸ü¶àÐÅÏ¢£¬Çë²Î¿¼Inside T-SQL Querying¡£

Íê³Éºó£¬ÔËÐÐÏÂÃæµÄ´úÂë½øÐÐÇåÀí£º

IF OBJECT_ID('dbo.fn_ConcatOrders') IS NOT NULL

  DROP FUNCTION dbo.fn_ConcatOrders;

ÐÔÄÜÎÊÌâ

µ±Äã°ÑÍⲿ±íµÄÊôÐÔ×÷ΪÊäÈëÌṩ¸ø±êÁ¿UDFʱ£¬ÔÚ²éѯÖе÷ÓÃÕâ¸öº¯ÊýµÄ³É±¾·Ç³£¸ß£¬ÄãÓ¦¸ÃÇå³þÕâÒ»µã¡£ÉõÖÁµ±º¯ÊýÖ»°üº¬Ò»¸ö´øÓбêÁ¿±í´ïʽµÄreturnbb ×Ó¾äʱ£¬ËüÒ²²»ÊÇÄÚÁª£¨inline£©º¯Êý¡£ÖðÐе÷Óøú¯ÊýµÄ¿ªÏú»áµ¼Ö·dz£¸ßµÄ³É±¾¡£ÔËÐÐÒ»¸ö¼òµ¥µÄÐÔÄܲâÊԾͿÉÒÔ·¢ÏÖ£¬Ïà¶ÔÓÚÄÚÁª±í´ïʽ£¨inline expression£©£¬ÔÚ²éѯÖÐʹÓÃUDFµÄ³É±¾·Ç³£¸ß¡£

ÔÚÔËÐÐÐÔÄܲâÊÔ֮ǰ£¬ÒªÈ·±£ÔÚÊý¾Ý¿âÖÐÒѾ­°üº¬ÁËNums±í¡£ÎÒÔÚµÚ1ÕÂÌṩÁË´´½¨ºÍÌî³äNums±íµÄ´úÂë¡£ÔÚSQL Server Management Studio £¨SSMS£©ÖÐÆôÓÃÖ´Ðкó·ÅÆú½á¹ûÑ¡ÏÕâÑùÄãµÄͳ¼Æ½á¹û½«²»°üº¬Éú³ÉÊä³öËù»¨·ÑµÄʱ¼ä¡£

ÏÈ´ÓNumsÖвéѯһ°ÙÍòÐУ¬²¢Ê¹ÓÃÒ»¸ön¼Ó1µÄÄÚÁª±í´ïʽ¡£

SELECT n, n+1 AS n2 FROM dbo.Nums WHERE n <= 1000000;

µÚÒ»´ÎÖ´ÐдúÂëʱ¿ÉÄÜҪɨÃèÎïÀíÊý¾Ý¡£Êý¾Ý±»¼ÓÔØµ½»º´æºó£¬ÔÙ´ÎÔËÐиòéѯ²¢Í³¼ÆÔËÐÐʱ¼ä¡£ÔÚÎÒµÄϵͳÉÏÔËÐиôúÂëʱ£¬Ëü²»µ½Ò»ÃëÖÓ¾ÍÍê³ÉÁË¡£

½ÓÏÂÀ´´´½¨fn_add1 UDF£º

IF OBJECT_ID('dbo.fn_add1') IS NOT NULL

  DROP FUNCTION dbo.fn_add1;

GO

CREATE FUNCTION dbo.fn_add1(@i AS INT) RETURNS INT

AS

BEGIN

  RETURN @i + 1;

END

GO

ʹÓÃfn_add1ÔËÐиòéѯ£º

SELECT n, dbo.fn_add1(n) AS n2 FROM dbo.Nums WHERE n <= 1000000;

²éѯºÄʱ3ÃëÖÓ¡£

ºóÃæÕâ¸ö²éѯµÄ¸ß³É±¾Óëÿ´Îº¯Êýµ÷ÓõĿªÏúÓйء£Äã¿ÉÒÔÔÚÖ´ÐвéѯʱÔËÐÐSQL Server ProfilerÀ´¸ú×ÙSP:Completed£¨»ò SP:Starting£©Ê¼þ£¬ÒÔ¹Û²ì¶ÔUDFµÄ¶à´Îµ÷Óá£

ΪÏÞÖÆ¸ú×ٵĴóС£¬Äã¿ÉÒÔÖ»²âÊÔ¼¸ÐС£ÀýÈ磬ʹÓÃɸѡÆ÷n<=10¡£Í¼6-1ÏÔʾÁËÎÒÔÚ¸ú×Ù²éѯʱµÃµ½µÄʼþ¡£

ͼ6-1  Profiler¸ú×Ù¶Ô±êÁ¿UDFµÄ¶à´Îµ÷ÓÃ

Õâʱ£¬¹Ø±ÕSSMSÖеÄÖ´Ðкó·ÅÆú½á¹ûÑ¡Ïî¡£

ÔÚ´úÂë¼òµ¥ÐÔºÍά»¤ÐÔ·½Ã棬ʹÓÃUDFÓÐÖî¶àºÃ´¦£¬²»¹ýÔÚÐÔÄÜ·½Ã棬Èç¹ûÄãÉè·¨ÔÚ²éѯÖÐʹÓÃÄÚÁª±í´ïʽʵÏÖ¼ÆËã²¢±ÜÃâʹÓÃUDF£¬Í¨³£»á¸üºÃЩ¡£ÓÐʱ£¬Ò»Ð©¿´ÆðÀ´ÐèҪѭ»·»ò¹ý³ÌÂß¼­µÄ¼ÆËã¾ÓȻҲ¿ÉÒÔʹÓÃÄÚÁª±í´ïʽʵÏÖ£¬ÄãÒ²Ðí»á¶Ô´Ë¸Ðµ½ºÜ³Ô¾ª¡£

ÀýÈ磬ÏÂÃæµÄ²éѯͳ¼Æ±äÁ¿ @findÖеÄ×Ö·û´®ÔÚCustomers. CompanyNameÁÐÖгöÏֵĴÎÊý¡£

DECLARE @find AS NVARCHAR(40);

SET @find = N'n';

SELECT CompanyName,

  (LEN(CompanyName+'*') - LEN(REPLACE(CompanyName, @find, '')+'*'))

    / LEN(@find) AS Cnt

FROM dbo.Customers;

±í6-2  ÒÔ¼ò»¯ÐÎʽÏÔʾÁ˲éѯËùÉú³ÉµÄ½á¹û

CompanyName

Cnt

Alfreds Futterkiste

0

Ana Trujillo Emparedados y helados

1

Antonio Moreno Taquer¨ªa

3

Around the Horn

2

Berglunds snabbköp

2

Ðø±í

CompanyName

Cnt

Blauer Saee Delikatessen

1

Blondesddsl p¨¨re et fils

1

B¨®lido Comidas preparadas

0

Bon app'

1

Bottom-Dollar Markets

0

¡­

¡­

¸Ã±í´ïʽʹÓÃREPLACEº¯Êý¼ÆËãºÏ¼ÆÊý¡£ËüµÄÂß¼­ÊÇÕâÑùµÄ£¬ÏȰÑ×Ö·û´®ÖеÄËùÓÐ @find¶¼É¾³ý£¨Ò²¾ÍÊÇÓᮡ¯Ìæ»»µô£©£¬È»ºó¼ì²éµÃµ½µÄ×Ö·û´®±ÈÔ­À´¶Ì¶àÉÙ£¬ÕâÑù¾Í¿ÉÒÔ¼ÆËã³ö @findÔÚ×Ö·û´®ÖгöÏֵĴÎÊý¡£ÐèҪעÒâµÄÊÇ£¬ÔÚ¼ÆËãËüÃǵij¤¶ÈʱΪÿ¸ö×Ö·û´®Ìí¼ÓÒ»¸ö¡°*¡±ÒÔ±ÜÃâµ±×Ö·û´®°üº¬Î²Ëæ¿Õ¸ñʱµÃµ½´íÎóµÄ³¤¶È¡£

ÔÚÔ¼ÊøÖÐʹÓÃUDF

±êÁ¿UDF¿ÉÒÔÓÃÓÚÔ¼Êø¡£ÕâÒ»½Ú½«ÌÖÂÛ²¢ÑÝʾÈçºÎÔÚDEFAULT¡¢CHECK¡¢PRIMARY KEYºÍUNIQUEÔ¼ÊøÖÐʹÓÃUDF¡£

DEFAULTÔ¼Êø

±êÁ¿UDF¿ÉÒÔÓÃÔÚDEFAULTÔ¼ÊøÖУ¬µ«ËüÓÐÒ»¸öÏÞÖÆ£¬µ±UDFÓÃÓÚDEFAULTÔ¼ÊøÊ±²»ÄܽÓÊոñíµÄÁÐ×÷ΪÊäÈë²ÎÊý¡£´úÂëÇåµ¥6-1ÖеĴúÂë´´½¨±íT1ºÍÃûΪfn_T1_getkeyµÄUDF£¬Ëü·µ»ØT1ÖÐȱÉÙµÄ×îС¼üÖµ¡£

´úÂëÇåµ¥6-1  ´´½¨±íT1 ºÍ fn_T1_getkey UDF

IF OBJECT_ID('dbo.T1') IS NOT NULL

  DROP TABLE dbo.T1;

GO

CREATE TABLE dbo.T1

(

  keycol INT NOT NULL CONSTRAINT PK_T1 PRIMARY KEY CHECK (keycol > 0),

  datacol VARCHAR(10) NOT NULL

);

GO

IF OBJECT_ID('dbo.fn_T1_getkey') IS NOT NULL

  DROP FUNCTION dbo.fn_T1_getkey;

GO

CREATE FUNCTION dbo.fn_T1_getkey() RETURNS INT

AS

BEGIN

  RETURN

    CASE

      WHEN NOT EXISTS(SELECT * FROM dbo.T1 WHERE keycol = 1) THEN 1       ELSE (SELECT MIN(keycol + 1)

            FROM dbo.T1 AS A

            WHERE NOT EXISTS

              (SELECT *

               FROM dbo.T1 AS B

               WHERE B.keycol = A.keycol + 1))

    END;

END

GO

ÏÂÃæµÄ´úÂëÏòkeycolÁÐÌí¼ÓÒ»¸öDEFAULTÔ¼Êø£¬¸ÃÔ¼Êøµ÷ÓÃfn_T1_getkeyº¯Êý£º

ALTER TABLE dbo.T1 ADD DEFAULT£¨dbo.fn_T1_getkey()£© FOR keycol;

×¢Òâ   Õâ¸öDEFAULTÔ¼ÊøÖ»ÔÚ²åÈëµ¥ÐÐʱִÐУ¬²åÈë¶àÐÐʱ²»»áÖ´ÐС£ÔÚʵ¼ÊµÄÒµÎñ·½°¸ÖÐÖØÓüüÖµ·Ç³£²»Ã÷ÖÇ¡£ÎÒʹÓÃÕâ¸öÀý×ÓÖ»ÊÇΪÁËÑÝʾ¶øÒÑ¡£

ÏÂÃæµÄ´úÂëÏÈÏò±íÖвåÈëÈýÐУ¬Éú³ÉµÄ¼üֵΪ1¡¢2¡¢3£¬È»ºóɾ³ý¼üֵΪ2µÄÐУ¬ÔÙ²åÈëÒ»¸öÐÂÐУ¬²¢Éú³É¼üÖµ2

INSERT INTO dbo.T1(datacol) VALUES('a');

INSERT INTO dbo.T1(datacol) VALUES('b');

INSERT INTO dbo.T1(datacol) VALUES('c');

DELETE FROM dbo.T1 WHERE keycol = 2;

INSERT INTO dbo.T1(datacol) VALUES('d');

ʹÓÃÏÂÃæµÄ´úÂë²éѯ¸Ã±í£¬Èç±í6-3Ëùʾ£¬¼üÖµ2±»¸³¸ø×îºó²åÈëµÄÐÐ(datacol=¡®d¡¯)£¬ÒòΪ¼üֵΪ2µÄÐÐ֮ǰ±»É¾³ý£º

SELECT * FROM dbo.T1;

±í6-3  T1 µÄÄÚÈÝ

Keycol

datacol

1

a

2

d

3

C

CHECKÔ¼Êø

²»Í¬ÓÚÔÚDEFAULTÔ¼ÊøÖÐʹÓõÄUDF£¬ÔÚCHECKÔ¼ÊøÖÐʹÓÃUDFʱ¿ÉÒÔÒýÓñíÖеÄÁÐ×÷ΪÊäÈë¡£ÔÚCHECKÔ¼ÊøÖÐʹÓÃUDF¿ÉÒÔʵÏÖ¹¦ÄÜÇ¿´óµÄÇ¿ÖÆÍêÕûÐÔ¹æÔò£¨integrity rule£©£¬ÕâÑùÄã¾Í¿ÉÒÔÔÚijЩÇé¿öϱÜÃâʹÓÃͨ³£³É±¾¸ü¸ßµÄ´¥·¢Æ÷¡£ÔÚ±¾ÕµĺóÃæ£¬ÎÒ½«ÑÝʾÈçºÎÔÚCHECKÔ¼ÊøÖÐʹÓÃUDF£¬Ê¾ÀýÖеÄUDF»ùÓÚÕýÔò±í´ïʽƥÅäÊäÈëµÄ×Ö·û´®¡£

PRIMARY KEY ºÍ UNIQUE Ô¼Êø

Äã¿ÉÒÔÔÚµ÷ÓÃUDFµÄ¼ÆËãÁÐÉÏ´´½¨UNIQUE »ò PRIMARY KEYÔ¼Êø¡£ÕâÁ½¸öÔ¼Êø»áÔÚºǫ́´´½¨Î¨Ò»Ë÷Òý¡£ÕâÒâζ×ÅÄ¿±ê¼ÆËãÁкÍËüµ÷ÓõÄUDF±ØÐëÂú×ãË÷Òý×¼Ôò£¨indexing guideline£©¡£ÀýÈ磬UDF±ØÐë°ó¶¨µ½¼Ü¹¹£¨Ê¹ÓÃSCHEMABINDINGÑ¡Ïî´´½¨£©£¬¼ÆËãÁбØÐë¾ßÓÐÈ·¶¨ÐÔÇÒÊǾ«È·µÄ£¬»òÕß¾ßÓÐÈ·¶¨ÐÔÇÒÊdz־õģ¬µÈµÈ¡£Äã¿ÉÒÔÔÚÁª»ú´ÔÊéÖÐÕÒµ½¹ØÓÚ¼ÆËãÁкÍUDFË÷Òý×¼ÔòµÄ¸üÏêϸÐÅÏ¢¡£

ÏÂÃæµÄ´úÂë³¢ÊÔÏòT1ÖÐÌí¼ÓÒ»¸öµ÷ÓÃfn_add1 UDFµÄ¼ÆËãÁÐcol1£¬²¢ÔÚ¸ÃÁÐÉÏ´´½¨Ò»¸öUNIQUEÔ¼Êø¡£

ALTER TABLE dbo.T1

  ADD col1 AS dbo.fn_add1(keycol) CONSTRAINT UQ_T1_col1 UNIQUE;

¸Ã²Ù×÷½«Ê§°Ü²¢·µ»ØÏÂÃæµÄ´íÎó£º

Msg 2729, Level 16, State 1, Line 1

Column 'col1' in table 'dbo.T1' cannot be used in an index or statistics or as a partition

key because it is non-deterministic.

Msg 1750, Level 16, State 0, Line 1

Could not create constraint. See previous errors.

²úÉú¸Ã´íÎóµÄÔ­ÒòÊǸú¯Êý²»Âú×ã´´½¨Ë÷ÒýµÄ±ØÒªÌõ¼þÖ®Ò»£¬¼´º¯Êý±ØÐë°ó¶¨µ½¼Ü¹¹¡£ÈçÄãËù¼û£¬¸Ã´íÎóÏûÏ¢±¾Éí²¢Î´Ö¸³ö¸Ã´íÎó²úÉúµÄÔ­Òò»ò½¨ÒéÄãÈçºÎ±ÜÃâ¸Ã´íÎó¡£Òª½â¾ö¸ÃÎÊÌ⣬ÄãÓ¦¸ÃΪ¸Ãº¯ÊýÔö¼ÓSCHEMABINDINGÑ¡Ïî¡£

ALTER FUNCTION dbo.fn_add1(@i AS INT) RETURNS INT

  WITH SCHEMABINDING

AS

BEGIN

  RETURN @i + 1;

END

GO

Ôٴγ¢ÊÔÌí¼Ó°üº¬UNIQUEÔ¼ÊøµÄ¼ÆËãÁУ¬ÕâÒ»´Î´úÂë¿ÉÒÔÕýÈ·ÔËÐС£

ALTER TABLE dbo.T1

  ADD col1 AS dbo.fn_add1(keycol) CONSTRAINT UQ_T1_col1 UNIQUE;

ÒªÔÚÕâÑùµÄ¼ÆËãÁÐÉÏ´´½¨PRIMARY KEYÔ¼ÊøÐèÒªÒ»µã¼¼ÇÉ¡£ÎÒÃÇÀ´¿´ÈçºÎʵÏÖ£¬ÏÈ´ÓT1ÖÐɾ³ýÒÑ´æÔÚµÄPRIMARY KEY¡£

ALTER TABLE dbo.T1 DROP CONSTRAINT PK_T1;

È»ºó³¢ÊÔÌí¼ÓÁíÒ»¸ö°üº¬PRIMARY KEYÔ¼ÊøµÄ¼ÆËãÁÐcol2¡£

ALTER TABLE dbo.T1

  ADD col2 AS dbo.fn_add1(keycol)

    CONSTRAINT PK_T1 PRIMARY KEY;

¸Ã³¢ÊÔ½«Ê§°Ü£¬²¢²úÉúÏÂÃæµÄ´íÎó£º

Msg 1711, Level 16, State 1, Line 1

Cannot define PRIMARY KEY constraint on column 'col2' in table 'T1'. The computed column has to be persisted and not nullable.

Msg 1750, Level 16, State 0, Line 1

Could not create constraint. See previous errors.

Äã±ØÐëÃ÷È·±£Ö¤col2ÓÀÔ¶²»»á³öÏÖNULLÖµ¡£Îª´Ë£¬Äã¿ÉÒÔ°ÑÁж¨ÒåΪPERSISTED ºÍ NOT NULL£¬¾ÍÏñÕâÑù£º

ALTER TABLE dbo.T1

  ADD col2 AS dbo.fn_add1(keycol) PERSISTED NOT NULL

    CONSTRAINT PK_T1 PRIMARY KEY;

PERSISTEDÑ¡ÏîÊÇSQL Server 2005ÖÐÐÂÔöµÄ¡£ÔÚSQL Server 2000ÖУ¬ÒªÔÚ¼ÆËãÁÐÉÏ´´½¨Ö÷¼üÔ¼Êø£¬Äã±ØÐëÓÃISNULLº¯Êý·â×°¶ÔUDFµÄµ÷Ó㬾ÍÏñÕâÑù£º

ALTER TABLE dbo.T1

  ADD col2 AS ISNULL(dbo.fn_add1(keycol), 0)

    CONSTRAINT PK_T1 PRIMARY KEY;

Íê³Éºó£¬ÔËÐÐÏÂÃæµÄ´úÂë½øÐÐÇåÀí¡£

IF OBJECT_ID('dbo.T1') IS NOT NULL

  DROP TABLE dbo.T1;

GO

IF OBJECT_ID('dbo.fn_T1_getkey') IS NOT NULL

  DROP FUNCTION dbo.fn_T1_getkey;

GO

IF OBJECT_ID('dbo.fn_T1_datacol_count') IS NOT NULL

  DROP FUNCTION dbo.fn_T1_datacol_count;

CLR ±êÁ¿ UDF

ÕâÒ»½Ú½éÉÜCLR±êÁ¿UDF²¢±È½ÏËüºÍT-SQL UDFÖ®¼äµÄ¹ØÏµ¡£¸½Â¼AÖÐÌṩÁËÄãÔÚ¿ª·¢¡¢Éú³É¡¢²¿ÊðºÍ²âÊÔCLR³ÌÐòʱӦ¸Ã×ñÑ­µÄ²Ù×÷Ö¸ÄÏ¡£ÔÚ±¾ÕÂÒÔ¼°ÆäËûÃèÊöCLR³ÌÐòµÄÕ½ÚÖУ¬ÎÒ½«Ö»¹Ø×¢³ÌÐò´úÂë±¾Éí¡£¸½Â¼ÖÐÌṩÁËÃüÃû¿Õ¼ä¶¨ÒåºÍCLRUtilitiesÀà¡£ÏÂÃæÊÇC# °æµÄÃüÃû¿Õ¼ä¶¨ÒåºÍCLRUtilitiesÀàµÄ¿ªÊ¼²¿·Ö¡£

using System;

using System.Data;

using System.Data.SqlClient;

using System.Data.SqlTypes;

using Microsoft.SqlServer.Server;

using System.Text;

using System.Text.RegularExpressions;

using System.Collections;

using System.Collections.Generic;

using System.Diagnostics;

using System.Reflection;

public partial class CLRUtilities

{

  ... ÕâÀïÊdzÌÐò¶¨Òå ...

}

ÏÂÃæÊÇVisual Basic°æ±¾µÄ´úÂ룺

Imports System

Imports System.Data

Imports System.Data.SqlClient

Imports System.Data.SqlTypes

Imports Microsoft.SqlServer.Server

Imports System.Text

Imports System.Text.RegularExpressions

Imports System.Collections

Imports System.Collections.Generic

Imports System.Diagnostics

Imports System.Reflection

Imports System.Runtime.InteropServices

Partial Public Class CLRUtilities

  ... ÕâÀïÊdzÌÐò¶¨Òå...

End Class

ÎÒ²»»áÔÚÕâÀïÖØ¸´ÃüÃû¿Õ¼äºÍÀàµÄ¶¨Òå¡£Ò²²»»áÌṩËùÉæ¼°µÄͨÓò½Ö裬ÕâЩÔÚ¸½Â¼ÖÐÒѾ­·Ç³£ÏêϸÁË¡£

CLR³ÌÐò

ÔÚSQL ServerÖпª·¢CLR³ÌÐòµÄÄÜÁ¦¸øÄãÌṩÁËÇ¿´óµÄ¹¦ÄÜ£¬µ«Í¬Ê±ËüÒ²´øÀ´Á˼«´óµÄ·çÏÕ¡£ .NET°üº¬Á˷ḻµÄ¿ª·¢¼¼ÊõÒÔ¼°ÔÚijЩÁìÓò±ÈT-SQL¸ü¸ßµÄÐÔÄÜ£¬T-SQLÓÀÔ¶²»»á±»Éè¼ÆÓÃÓÚ¸ßЧµØ´¦ÀíÕâЩÁìÓò¡£ÕâЩÁìÓò°üÀ¨¸´ÔÓ¼ÆËã¡¢±éÀúºÍ¹ý³ÌÂß¼­¡¢×Ö·û´®´¦Àí¡¢¶Ô²Ù×÷ϵͳ×ÊÔ´µÄÍⲿ·ÃÎʵȵȡ£T-SQLÊÇÒ»ÖÖÉùÃ÷ʽÓïÑÔ£¨declarative language£©¡£µ±Ê¹ÓûùÓÚ¼¯ºÏµÄ²éѯ½øÐÐÊý¾Ý²Ù×÷ʱ£¬Ëü±È .NETÓµÓиüÇ¿´óµÄ¹¦Äܺ͸ü¸ßµÄÐÔÄÜ¡£¼¯³É .NETµÄΣÏÕÔÚÓÚ£¬¶ÔÓÚÄÇЩ»¹Î´¾ß±¸SQL˼ά·½Ê½µÄ¿ª·¢ÈËÔ±À´ËµËüÒ²ÊÇÒ»¸öý½é£¬»áµ¼ÖÂËûÃÇ¿ª·¢³öÐÔÄÜÔã¸âµÄ´úÂë¡£ÔÚ±¾ÊéÖУ¬ÎÒ½«ÌṩһЩӦ¸ÃʹÓà .NET¿ª·¢µÄʾÀý¡£

¸ü¶àÐÅÏ¢  ¹ØÓÚ»ùÓÚ¼¯ºÏµÄ²éѯºÍ¸ßЧµÄ»ùÓÚ¼¯ºÏ½â¾ö·½°¸µÄÐÅÏ¢£¬Çë²Î¿¼Inside T-SQL QueryingÒ»Ê飬¸ÃÊé¸üΪÉîÈëµÄ½éÉÜÁËÕâЩÖ÷Ìâ¡£

ÕýÔò±í´ïʽ

ÕýÔò±í´ïʽΪÄãÌṩÁËÒ»ÖÖ¹¦ÄÜÇ¿´óµÄ·½·¨£¬¿ÉÒÔÀûÓÃһЩ¼òÃ÷Áé»îµÄ·ûºÅÆ¥ÅäÎı¾µÄģʽ£¨patterns of text£©¡£ANSI SQL¶¨ÒåÁËSIMILAR TOν´ÊÒÔÖ§³ÖÕýÔò±í´ïʽ£¬²»ÐÒµÄÊÇ£¬SQL Server 2005²¢Î´ÔÚT-SQLÖÐʵÏÖ¸Ãν´Ê¡£µ«Äã¿ÉÀûÓà .NET´úÂëÖеÄÕýÔò±í´ïʽ¡£ÀýÈ磬ÏÂÃæµÄC# ´úÂ붨ÒåÁËÒ»¸öÃûΪfn_RegExMatchµÄº¯Êý¡£

// ʹÓÃÕýÔò±í´ïʽÑéÖ¤ÊäÈëµÄ×Ö·û´®

[SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.None)]

public static SqlBoolean fn_RegExMatch(SqlString inpStr,

  SqlString regExStr)

{

    if (inpStr.IsNull || regExStr.IsNull)

        return SqlBoolean.Null;

    else

        return (SqlBoolean)Regex.IsMatch(inpStr.Value, regExStr.Value ,

          RegexOptions.CultureInvariant);

}

·½·¨Í·ÖеÄÊôÐÔ֪ͨSQL Server¸Ã·½·¨¾ßÓÐÈ·¶¨ÐÔ²¢ÇÒ²»Éæ¼°Êý¾Ý·ÃÎÊ¡£×¢Òâ´úÂëʹÓÃÁËRegexOptions.CultureInvariantÑ¡ÏîÒÔ»ñµÃÎÄ»¯ÖÐÁ¢£¨culture-independent£©µÄÆ¥Åä½á¹û¡£Èç¹ûÆ¥ÅäÊÇÎÄ»¯ÒÀÀµ£¨culture-dependent£©µÄ£¬¸Ã·½·¨½«²»¾ßÓÐÈ·¶¨ÐÔ¡££¨ÏêÇéÇë²Î¼ûhttp://msdn2.microsoft.com/en-us/library/z0sbec17.aspx£©¡£

¸Ãº¯Êý½ÓÊÕÒ»¸ö×Ö·û´®£¨inpStr£©ºÍÒ»¸öÕýÔò±í´ïʽ£¨regExStr£©×÷ΪÊäÈë¡£º¯ÊýµÄ·µ»ØÀàÐÍÊÇSqlBoolean£¬ËüÓÐÈýÖÖ¿ÉÄܵÄÖµ£º0¡¢1ºÍNull¡£Èç¹ûregExStr»òinpStrÊÇNullÔò·µ»ØÖµÎªNull£¬Èç¹ûÔÚinpStrÖÐÕÒµ½regExStrģʽÔò·µ»Ø1£¬Ôò·ñ·µ»Ø0¡£ÈçÄãËù¼û£¬¸Ãº¯ÊýµÄ´úÂë·Ç³£¼òµ¥¡£´úÂëÊ×ÏȲâÊÔÊäÈë²ÎÊýÊÇ·ñΪNULL£¬Èç¹ûÓÐÒ»¸öÊÇNULLÔò·µ»ØNULL¡£Èç¹ûÊäÈë²ÎÊý¶¼²»ÎªNULL£¬Ôòº¯Êý·µ»ØRegEx.IsMatch·½·¨µÄ½á¹û¡£Õâ¸ö·½·¨¼ì²éµÚÒ»¸ö²ÎÊýËùÌṩµÄ×Ö·û´®ÊÇ·ñ°üº¬µÚ¶þ¸ö²ÎÊýÖÐÌṩµÄģʽ¡£RegEx.IsMatch·½·¨·µ»Ø .NETµÄSystem.BooleanÖµ£¬¸ÃÖµ±ØÐëÏÔʽת»»ÎªSqlBoolean¡£

Ò²ÐíÄã¸üϲ»¶Ê¹ÓÃVisual Basic£¬ÏÂÃæ¾ÍÊÇʹÓÃVisual BasicʵÏֵĺ¯Êý´úÂë¡£

' ʹÓÃÕýÔò±í´ïʽÑéÖ¤ÊäÈëµÄ×Ö·û´®

<SqlFunction(IsDeterministic:=True, DataAccess:=DataAccessKind.None)> _

Public Shared Function fn_RegExMatch(ByVal inpStr As SqlString, _

  ByVal regExStr As SqlString) As SqlBoolean

    If (inpStr.IsNull Or regExStr.IsNull) Then

        Return SqlBoolean.Null

    Else

        Return CType(Regex.IsMatch(inpStr.Value, regExStr.Value, _

          RegexOptions.CultureInvariant), SqlBoolean)

    End If

End Function

Èç¹ûÄã×ñÑ­Á˸½Â¼AÖÐÃèÊöµÄÖ¸µ¼£¬ÄÇôÄãÒѾ­×÷ºÃÁ˲âÊÔºÍʹÓøú¯ÊýµÄ×¼±¸ÁË¡£ÕâЩָµ¼°üº¬£ºÔÚSQL ServerÖ줻îCLR£¨Ä¬ÈÏÊǽûÓõģ©¡¢´´½¨ÃûΪCLRUtilitiesµÄ²âÊÔÊý¾Ý¿â£¬ÔÚMicrosoft Visual Studio 2005Öпª·¢´úÂ룬ÔÚ´ÅÅÌÉÏÉú³É .dll³ÌÐò¼¯¡¢´Ó³ÌÐò¼¯ÖаÑIntermediate Language£¨IL£©´úÂë¼ÓÔØµ½SQL ServerÊý¾Ý¿â£¬²¢ÔÚÊý¾Ý¿âÖÐ×¢²á³ÌÐò¼¯ÖеijÌÐò¡£ÔËÐÐÏÂÃæµÄ´úÂëÀ´¼¤»îSQL ServerÖеÄCLR²¢´´½¨CLRUtilities²âÊÔÊý¾Ý¿â¡£

SET NOCOUNT ON;

USE master;

EXEC sp_configure 'clr enabled', 1;

RECONFIGURE;

GO

IF DB_ID('CLRUtilities') IS NOT NULL

  DROP DATABASE CLRUtilities;

GO

CREATE DATABASE CLRUtilities;

GO

USE CLRUtilities;

GO

×¢Òâ   ¿ªÆô'clr enabled'·þÎñÅäÖÃÑ¡ÏĬÈÏÊǽûÓõģ©ºó£¬¾Í±íʾMicrosoft SQL Server¿ÉÒÔÔÚʵÀý¼¶±ðÉÏÔËÐÐÓû§ºÍÐò¼¯¡£Äã²»ÄÜÔÚ¸üϸµÄÁ£¶È¼¶±ðÉÏ¿ØÖƸÃÑ¡ÏËùÒÔ£¬¼¤»î¸ÃÑ¡ÏÄã¾ÍΪÕû¸öSQL ServerʵÀýÉϼ¤»îÁ˸ÃÑ¡Ïî¡£¼¤»î¸ÃÑ¡Ïî¿ÉÄܻᵼÖ°²È«·çÏÕ¡£·çÏյļ¶±ðÈ¡¾öÓÚÄãÔÊÐíÿ¸ö³ÌÐòÖ´ÐÐʲô²Ù×÷¡£µ±Ê¹ÓÃCREATE ASSEMBLYÃüÁî´´½¨³ÌÐò¼¯Ê±£¬Í¨¹ý°ÑPERMISSION_SETÑ¡ÏîÉèÖÃΪSAFE¡¢ EXTERNAL_ACCESS »ò UNSAFE¿ÉÒÔ¿ØÖÆ´úÂëµÄ·ÃÎÊȨÏÞ¡£ÏÂÃæÊÇÁª»ú´ÔÊéÃèÊöÕâÈý¸öÑ¡ÏîʱµÄ°²È«ËµÃ÷£º
¶ÔÓÚÖ´ÐмÆËãºÍÊý¾Ý¹ÜÀíÈÎÎñ¶øÎÞÐè·ÃÎÊ SQL Server ʵÀýÍⲿ×ÊÔ´µÄ³ÌÐò¼¯£¬SAFE ÊÇÍÆ¼öµÄȨÏÞ¼¯¡£
¶ÔÓÚ·ÃÎÊ SQL Server ʵÀýÍⲿ×ÊÔ´µÄ³ÌÐò¼¯£¬ÎÒÃÇÍÆ¼öʹÓà EXTERNAL_ACCESS¡£EXTERNAL_ACCESS ³ÌÐò¼¯°üº¬ SAFE ³ÌÐò¼¯µÄ¿É¿¿ÐԺͿÉÉìËõÐÔ±£»¤£¬µ«´Ó°²È«½Ç¶È¶øÑÔ£¬ËüÓë UNSAFE ³ÌÐò¼¯ÀàËÆ¡£Ô­ÒòÊÇÔÚĬÈÏÇé¿öÏ£¬EXTERNAL_ACCESS ³ÌÐò¼¯ÖеĴúÂëÒÔ SQL Server ·þÎñÕË»§Éí·ÝÔËÐв¢·ÃÎÊ´ËÕË»§µÄÍⲿ×ÊÔ´£¬³ý·Ç´Ë´úÂëÏÔʽģÄâµ÷Ó÷½¡£Òò´Ë£¬´´½¨ EXTERNAL_ACCESS ³ÌÐò¼¯µÄȨÏÞÓ¦Ö»ÊÚÓèÒÔ SQL Server ·þÎñÕË»§Éí·ÝÔËÐдúÂëµÄ¿ÉÐŵǼ¡£ÓйØÄ£ÄâµÄÏêϸÐÅÏ¢£¬Çë²ÎÔÄ CLR Integration Security¡£
Ö¸¶¨ UNSAFE ½«Ê¹³ÌÐò¼¯µÄ´úÂëÔÚ SQL Server ½ø³Ì¿Õ¼äÖÐÖ´ÐÐÈÎÒâ²Ù×÷£¬ÕâЩ²Ù×÷ÓпÉÄÜÆÆ»µSQL ServerµÄ½¡×³ÐÔ¡£UNSAFE ³ÌÐò¼¯»¹¿ÉÄÜ»áÆÆ»µ SQL Server »òCommon Language RuntimeµÄ°²È«ÏµÍ³¡£UNSAFE ȨÏÞÖ»Ó¦ÊÚÓè¸ß¶È¿ÉÐŵijÌÐò¼¯¡£Ö»ÓÐ sysadmin ¹Ì¶¨·þÎñÆ÷½ÇÉ«µÄ³ÉÔ±²ÅÄÜ´´½¨²¢ÐÞ¸ÄUNSAFE ³ÌÐò¼¯¡£

±¾ÕÂËùÌÖÂ۵ĺ¯Êý¶¼²»ÐèÒª·ÃÎÊÍⲿ×ÊÔ´£¬ËùÒÔ´´½¨³ÌÐò¼¯Ê±½«Ê¹ÓÃSAFEȨÏÞ¼¯£¨permission set£©¡£ÔÚÏÂÒ»ÕÂÖУ¬ÎÒ½«ÑÝʾһ¸öÐèÒªEXTERNAL_ACCESSȨÏÞ¼¯µÄ´æ´¢¹ý³ÌºÍÒ»¸öÐèÒªUNSAFEȨÏÞ¼¯µÄ´¥·¢Æ÷£¬µ«Ö»ÊdzöÓÚÑÝʾĿµÄ¡£ÑÝʾÕâЩ³ÌÐòʱ£¬ÎÒ½«Ð޸ĸóÌÐò¼¯ÒÔÖ§³ÖËùÐèÒªµÄȨÏÞ¼¯¡£ÔÊÐí³ÌÐò¼¯½øÐÐÍⲿ·ÃÎÊ»á´øÀ´°²È«·çÏÕ£¬ÀμÇÕâÒ»µã¡£

ÔÚºóÃæµÄËùÓеÄʾÀýÖУ¬ÎÒ¶¼¼ÙÉèÒÑ´æÔÚCLRUtilitiesÊý¾Ý¿â²¢ÇÒÒѾ­Ê¹ÓÃVisual StudioÉú³É³ÌÐò¼¯¡£Èç¹ûÄ㻹ûÓаѳÌÐò¼¯¼ÓÔØµ½Êý¾Ý¿â£¬ÔËÐÐÏÂÃæµÄ´úÂëÍê³É¸Ã²Ù×÷¡£

 USE CLRUtilities;

GO

CREATE ASSEMBLY CLRUtilities

FROM 'C:\CLRUtilities\CLRUtilities\bin\Debug\CLRUtilities.dll'

WITH PERMISSION_SET = SAFE;

-- Èç¹ûûÓÐDebug Îļþ¼Ð£¬ÔòʹÓÃÕâ¸öµØÖ·:

-- FROM 'C:\CLRUtilities\CLRUtilities\bin\CLRUtilities.dll'

µ±È»£¬Èç¹û°üº¬³ÌÐò¼¯µÄCLRUtilities.dllÎļþλÓÚÁíÒ»¸öÎļþ¼Ð£¬ÔòÌæ»»ÎªËüËùÔÚµÄÎļþ¼Ð¡£CREATE ASSEMBLY ÃüÁî°ÑIL´úÂë´Ó .dllÎļþ¼ÓÔØµ½Êý¾Ý¿â¡£Ò»µ©¼ÓÔØ£¬Äã¾Í²»ÔÙÐèÒªÍⲿÎļþÁË¡£Òª×¢ÒâµÄÊÇ£¬Èç¹ûÄãÌí¼Ó³ÌÐòºóÖØÐÂÉú³ÉÁ˳ÌÐò¼¯£¬¶øÇÒÔÚVisual Studio Professional°æÖÐδѡÔñ×Ô¶¯²¿ÊðÑ¡ÏÄãÐèÒªÖ´ÐÐALTER ASSEMBLY »ò DROP ºÍCREATE ASSEMBLYÃüÁÊÖ¹¤°ÑIL´úÂëÖØÐ¼ÓÔØµ½Êý¾Ý¿â¡£Èç¹ûÄã×ñÑ­Á˸½Â¼AÖеÄÖ¸µ¼¶øÇÒÒѾ­´´½¨Á˱¾ÊéÖÐÌÖÂÛµÄËùÓгÌÐò£¬¿ÉÒÔÊ¡ÂÔÕâÒ»²½Öè¡£ÒÔºóÎÒ²»ÔÙÌá¼°ÕâÒ»²½¡£

ÔÚÌÖÂÛеijÌÐòʱ£¬ÎÒ»áÌṩÔÚÊý¾Ý¿â×¢²áËüÃÇËùÐèµÄT-SQL´úÂ루CREATE FUNCTION | PROCEDURE | TRIGGERÃüÁ£¬¾¡¹ÜÈç¹ûÄãÍêÈ«×ñÑ­¸½Â¼AÖеÄÖ¸µ¼£¬Êµ¼ÊÉϲ¢²»ÐèÒªÔËÐÐÕâЩ´úÂë¡£

ÏÂÃæÊÇÄãÐèÒªÔÚCLRUtilitiesÊý¾Ý¿âÖÐ×¢²áC#  °æfn_RegExMatchËùÐèµÄ´úÂë¡£

USE CLRUtilities;

GO

IF OBJECT_ID('dbo.fn_RegExMatch') IS NOT NULL

  DROP FUNCTION dbo.fn_RegExMatch;

GO

CREATE FUNCTION dbo.fn_RegExMatch

  (@inpstr AS NVARCHAR(MAX), @regexstr AS NVARCHAR(MAX))

RETURNS BIT

EXTERNAL NAME CLRUtilities.CLRUtilities.fn_RegExMatch;

ÏÂÃæÊÇ×¢²á Visual Basic°æfn_RegExMatchµÄ´úÂë¡£

CREATE FUNCTION dbo.fn_RegExMatch

  (@inpstr AS NVARCHAR(MAX), @regexstr AS NVARCHAR(MAX))

RETURNS BIT

EXTERNAL NAME CLRUtilities.[CLRUtilities.CLRUtilities].fn_RegExMatch;

×¢Òâ    ÔÚ×¢²áC# °æ±¾ºÍVisual Basic°æ±¾µÄº¯Êýʱ£¬ÎªÆäÖ¸¶¨Á˲»Í¬µÄEXTERNALNAME (CLRUtilities CLRUtilities.fn_RegExMatchºÍCLRUtilities.[CLRUtilities. CLRUtilities].fn_RegExMatch)¡£ÕâÒ»µã·Ç³£ÁíÈËÃÔ»ó¡£ÔÚ֮ǰµÄ .NET°æ±¾ÖÐ(2002,2003)£¬µ±Äã´´½¨ÁËÒ»¸öÀà¿âʱ£¬C# »áÓúÍÀàÏàͬµÄÃû³ÆÌí¼Ó¸ùÃüÃû¿Õ¼ä(root namespace)£¬¶øVisual Basic²»ÊÇÕâÑù¡£Õâ¾Íµ¼ÖÂÁ˲»Í¬µÄ½á¹û£ºVisual Basic´´½¨ÁËÒ»¸ö¸ùÃüÃû¿Õ¼ä£¬¶øC# ²»»á¡£Îª±£Ö¤Ê¹Óò»Í¬ .NETÓïÑÔʱT-SQL´úÂëµÄÒ»ÖÂÐÔ£¬ÔÚʹÓÃVisual Basic±à³Ìʱ±ØÐë±ÜÃâ´´½¨¸ùÃüÃû¿Õ¼ä¡£ÔÚVisual StudioÖУ¬ÓÒ¼üµ¥»÷¸ÃÏîÄ¿£¬Ñ¡ÔñÊôÐÔ¡¢Ó¦ÓóÌÐòÒ³¡£Çå¿Õ¡°¸ùÃüÃû¿Õ¼ä¡±Îı¾¿òµÄÄÚÈÝ¡£ÔÚ±¾ÊéÖУ¬ÎÒ½«¼ÙÉèÄãδÇå¿Õ¸ÃÑ¡ÏÒò´Ë£¬µ±×¢²á¶ÔÏóʱÄã»á¿´µ½Ö¸¶¨µÄÍⲿÃû³ÆµÄ²îÒì¡£

ÕâÑùÄã¾Í¿ÉÒÔʹÓÃfn_RegExMatchº¯ÊýÁË¡£

¸ü¶àÐÅÏ¢  Äã¿ÉÒÔÔÚ»¥ÁªÍøÉÏÕÒµ½¸ü¶àÓÐÓõÄÕýÔò±í´ïʽ¡£ÀýÈ磺http://www.regexlib. com¡£

×÷Ϊһ¸öʹÓÃÕâ¸öк¯ÊýµÄʾÀý£¬¼ÙÉèÄãÏë¼ì²éÒ»¸öE-mailµØÖ·ÊÇ·ñÓÐЧ£¬Äã¿ÉÒÔʹÓÃÕâ¸öÕýÔò±í´ïʽ£ºN'^([\w-]+\.)*?[\w-]+@[\w-]+\.([\w-]+\.)*?[\w]+$'.

¸ÃÕýÔò±í´ïʽ¼ì²éµØÖ·ÊÇ·ñÒÔÒ»¸öµ¥´ÊΪ¿ªÍ·£¬°üº¬¡°at¡±£¨@£©·ûºÅ£¬¶øÇÒÔÚ@·ûºÅÖ®ºóÖÁÉÙÓÐÁ½¸öµ¥´Ê£¬µ¥´ÊÖ®¼äÓõã(.)·Ö¸ô¡£ÔÚ@·ûºÅµÄÇ°ÃæºÍºóÃæ£¬¿ÉÒÔ°üº¬ÆäËûһЩÒÔµã·Ö¸ôµÄµ¥´Ê¡£Õâ¸öÕýÔò±í´ïʽ·Ç³£¼òµ¥£¬Ìṩ¸ÃÕýÔò±í´ïʽֻÊÇΪÁËÑÝʾ£¬ÒªÑ§Ï°ÈçºÎ±àд¸ü½¡×³¸üÍêÕûµÄÕýÔò±í´ïʽ£¬½¨ÒéÄã·ÃÎÊhttp://www.regularexpressions.info/¡£

ÏÂÃæµÄ´úÂë·µ»Ø1£¬ÒòΪËüËùÌṩµÄE-mailµØÖ·ÊÇÓÐЧµÄ¡£

SELECT dbo.fn_RegExMatch(

  N'dejan@solidqualitylearning.com',

  N'^([\w-]+\.)*?[\w-]+@[\w-]+\.([\w-]+\.)*?[\w]+$');

¶øÏÂÃæµÄ´úÂ뽫·µ»Ø0£¬ÒòΪ¸ÃµØÖ·ÎÞЧ¡£

SELECT dbo.fn_RegExMatch(

  N'dejan#solidqualitylearning.com',

  N'^([\w-]+\.)*?[\w-]+@[\w-]+\.([\w-]+\.)*?[\w]+$');

Ä㻹¿ÉÒÔÔÚCHECKÔ¼ÊøÖÐʹÓøú¯Êý¡£ÀýÈ磬ÏÂÃæµÄ´úÂë»á´´½¨Ò»¸öʹÓÃCHECKÔ¼ÊøµÄTestRegEx±í£¬¸ÃÔ¼ÊøÏÞÖÆÁËjpgfilenameÁеÄÖµ±ØÐëÊÇÒÔjpgΪÀ©Õ¹ÃûµÄÎļþÃû¡£

IF OBJECT_ID('dbo.TestRegEx') IS NOT NULL

  DROP TABLE dbo.TestRegEx;

GO

CREATE TABLE dbo.TestRegEx

(

  jpgfilename NVARCHAR(4000) NOT NULL

  CHECK(dbo.fn_RegExMatch(jpgfilename,

    N'^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w ]*.*))+\.(jpg|JPG)$')

      = CAST(1 As BIT))

);

JpgfilenameÁеÄÖµ±ØÐëÂú×ãÏÂÃæµÄģʽ£ºÒÔÒ»¸öAµ½ZÖ®¼äµÄ×Öĸ¿ªÍ·£¬ºó¸úÒ»¸öðºÅ£¨ÅÌ·û£©£¬»òÕßÊÇÁ½¸ö·´Ð±ÏߺÍÒ»¸öµ¥´Ê£¨ÍøÂç¹²Ïí£©¡£¶øÇÒ¸ÃÖµ±ØÐëÖÁÉÙ°üº¬Ò»¸ö±íʾ´ÅÅÌ»ò¹²ÏíµÄ¸ùĿ¼µÄ·´Ð±Ïß¡£È»ºó£¬¸ÃÖµ¿ÉÒÔÔÙ°üº¬Ò»Ð©±íʾ¶à¸ö×ÓÎļþ¼ÐµÄ·´Ð±Ïß/×Ö·ûµÄ×éºÏ¡£×îºó¼¸¸ö×Ö·û±ØÐëÊÇ¡°. jpg¡±£¨´óд»òСд£©¡£

ÏÂÃæ°üº¬ÓÐЧJPEGÎļþÃûµÄINSERT¿ÉÒÔ±»½ÓÊÜ£º

INSERT INTO dbo.TestRegEx(jpgfilename) VALUES(N'C:\Temp\myFile.jpg');

INSERT INTO dbo.TestRegEx(jpgfilename) VALUES(N'\\MyShare\Temp\myFile.jpg');

INSERT INTO dbo.TestRegEx(jpgfilename) VALUES(N'\\MyShare\myFile.jpg');

INSERT INTO dbo.TestRegEx(jpgfilename) VALUES(N'C:\myFile.jpg');

¶øÏÂÃæ°üº¬ .txtÎļþÃûµÄINSERT»á±»¾Ü¾ø£º

INSERT INTO dbo.TestRegEx(jpgfilename) VALUES(N'C:\Temp\myFile.txt');

INSERT INTO dbo.TestRegEx(jpgfilename) VALUES(N'\\MyShare\\Temp\myFile.jpg');

INSERT INTO dbo.TestRegEx(jpgfilename) VALUES(N'\\myFile.jpg');

INSERT INTO dbo.TestRegEx(jpgfilename) VALUES(N'C:myFile.jpg');

Íê³Éºó£¬ÔËÐÐÏÂÃæµÄ´úÂë½øÐÐÇåÀí£º

IF OBJECT_ID('dbo.TestRegEx') IS NOT NULL

  DROP TABLE dbo.TestRegEx;

GO

IF OBJECT_ID('dbo.fn_RegExMatch') IS NOT NULL

  DROP FUNCTION dbo.fn_RegExMatch;

ÏÔʽºÍÒþʽת»»

ÔÚSQL Server 2005Öпª·¢CLR¶ÔÏóʱ£¬Äã¿ÉÒÔʹÓà .NET±¾»úÀàÐÍ£¨native type£©ºÍ .NET SQLÀàÐÍÀ´¶¨ÒåÊäÈë/Êä³ö²ÎÊýºÍ±äÁ¿¡£.NET SQLÀàÐÍÓ³Éäµ½SQL ServerÀàÐÍʱ¸ü¾«È·¡£ÔÚ³ÌÐò½Ó¿ÚÖÐʹÓà .NET±¾»úÀàÐͻᵼÖÂÓëSQL Server»òµ½SQL ServerµÄ´«µÝֵʱ·¢ÉúÒþʽת»»¡£Ò»Ð©¿ª·¢ÈËÔ±¸üÀÖÒâʹÓà .NET SQLÀàÐÍ£¬ÒòΪËûÃÇÏàÐÅÒþʽת»»»á²úÉúÐÔÄÜËðºÄ¡£µ«ÕâÑùÓÐһЩÏÞÖÆ£¬ÒòΪ .NET SQLÀàÐÍÔÚ¹¦ÄÜ·½Ã沢ûÓÐ .NET±¾»úÀàÐͷḻ¡£ÀýÈ磬.NETµÄ±¾»úÀàÐÍSystem.String£¨C# ÖÐÊÇstring, Visual BasicÊÇString£©ÌṩÁËSubstring·½·¨£¬¶ø .NET SQLµÄ SqlStringÀàÐÍÔòûÓС£

¾¡¹ÜÐÔÄܲ¢²»ÊÇËüÃÇÕæÕýµÄ²î±ð¡£µ«ÎÒ»¹Êǽ¨ÒéÄãÔÚ´´½¨CLR¶ÔÏóµÄ .NET´úÂëÖÐʹÓÃSQLÀàÐÍ£¬ÒòΪ .NET±¾»úÀàÐͲ»Ö§³ÖNULLÖµ¡£ÀýÈ磬Èç¹ûʵÏÖfn_RegExMatchº¯ÊýʱûÓÐʹÓÃSqlStringÀàÐͶøÊÇʹÓà .NET string±¾»úÀàÐÍ×÷Ϊ²ÎÊý£¬ÔÚ´úÂë¼ì²é²ÎÊýÖµÊÇ·ñΪNULLµØ·½Äã»áÊÕµ½Ò»¸ö±àÒë´íÎó¡£Èç¹ûÄãʹÓà .NET string ÀàÐͲ¢Ìø¹ýNULL¼ì²é£¬µ±ÓÃNULL²ÎÊýµ÷ÓÃËüʱº¯Êý½«·µ»ØÒ»¸öÒì³£¡£Èç¹ûÄãÐèÒª .NET±¾»úÀàÐÍÌṩµÄÆäËû¹¦ÄÜ£¬Äã±ØÐëÖ´ÐÐһЩÏÔʽת»»¡£´ËÍ⣬Äã¿ÉÒÔʹÓÃSQLÀàÐͱäÁ¿µÄValueÊôÐԵõ½ .NET±¾»úÀàÐ͵ÄÖµ£¬°Ñ¸ÃÖµ±£´æÔÚÒ»¸ö .NET±¾»úÀàÐ͵ıäÁ¿ÖУ¬ÕâÑù¾Í¿ÉÒÔʹÓñ¾»úÀàÐ͵ÄËùÓг£¹æÊôÐԺͷ½·¨ÁË¡£ÔÚfn_RegExMatchº¯ÊýÖУ¬RegEx.IsMatchÐèÒª .NET string ÀàÐÍ×÷ΪÊäÈ룻ͨ¹ý .NET SQLÀàÐ͵ÄValueÊôÐԵõ½¸ÃÖµ¡£¸Ã·½·¨µÄ·µ»ØÀàÐÍÊÇÒ»¸ö .NET±¾»úÀàÐÍBoolean£¬ËùÒÔ´úÂë°ÑËüÏÔʽת»»ÎªSqlBoolean¡£

ÕâÒ»½Ú½«Ö¤Ã÷Òþʽת»»ºÍÏÔʽת»»Ö®¼äµÄÐÔÄܲîÒìÆäʵ²¢²»ÊǺÜÃ÷ÏÔ¡£ÏÂÃæµÄC# ´úÂ붨ÒåÁ˺¯Êýfn_ImpCastºÍfn_ExpCast£¬Ç°ÕßʹÓà .NET±¾»úÀàÐͺÍÒþʽת»»£¬¶øºóÕßÔòʹÓà .NET SQLÀàÐͺÍÏÔʽת»»¡£

// ±È½ÏÒþʽת»»ºÍÏÔʽת»»

[SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.None)]

public static string fn_ImpCast(string inpStr)

{

    return inpStr.Substring(2, 3);

}

[SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.None)]

public static SqlString fn_ExpCast(SqlString inpStr)

{

    return (SqlString)inpStr.ToString().Substring(2, 3);

}

ÏÂÃæÊǶ¨Òå¸Ãº¯ÊýµÄVisual Basic´úÂ룺

'±È½ÏÒþʽת»»ºÍÏÔʽת»»

<SqlFunction(IsDeterministic:=True, DataAccess:=DataAccessKind.None)> _

Public Shared Function fn_ImpCast(ByVal inpStr As String) As String

    Return inpStr.Substring(2, 3)

End Function

<SqlFunction(IsDeterministic:=True, DataAccess:=DataAccessKind.None)> _

Public Shared Function fn_ExpCast(ByVal inpStr As SqlString) As SqlString

    Return CType(inpStr.ToString().Substring(2, 3), SqlString)

End Function

ÏÂÃæÊÇÔÚÊý¾Ý¿âÖÐ×¢²áC#°æº¯ÊýµÄ´úÂ룺

IF OBJECT_ID('dbo.fn_ImpCast') IS NOT NULL

  DROP FUNCTION dbo.fn_ImpCast;

GO

IF OBJECT_ID('dbo.fn_ExpCast') IS NOT NULL

  DROP FUNCTION dbo.fn_ExpCast;

GO

-- ´´½¨ fn_ImpCast º¯Êý

CREATE FUNCTION dbo.fn_ImpCast(@inpstr AS NVARCHAR(4000))

RETURNS NVARCHAR(4000)

EXTERNAL NAME CLRUtilities.CLRUtilities.fn_ImpCast;

GO

-- ´´½¨ fn_ExpCast º¯Êý

CREATE FUNCTION dbo.fn_ExpCast(@inpstr AS NVARCHAR(4000))

RETURNS NVARCHAR(4000)

EXTERNAL NAME CLRUtilities.CLRUtilities.fn_ExpCast;

ÏÂÃæµÄ´úÂë×¢²áVisual Basic°æµÄº¯Êý£º

--´´½¨fn_ImpCastº¯Êý

CREATE FUNCTION dbo.fn_ImpCast(@inpstr AS NVARCHAR(4000))

RETURNS NVARCHAR(4000)

EXTERNAL NAME CLRUtilities.[CLRUtilities.CLRUtilities].fn_ImpCast;

GO

-- ´´½¨fn_ExpCastº¯Êý

CREATE FUNCTION dbo.fn_ExpCast(@inpstr AS NVARCHAR(4000))

RETURNS NVARCHAR(4000)

EXTERNAL NAME CLRUtilities.[CLRUtilities.CLRUtilities].fn_ExpCast;

ÏÂÃæµÄ´úÂëͨ¹ýÑ­»·µ÷ÓÃÒ»°ÙÍò´Îfn_ImpCast£¬ÔËÐÐÁË16Ã룺

SET NOCOUNT ON;

GO

DECLARE @a AS NVARCHAR(4000);

DECLARE @i AS INT;

SET @i = 1;

WHILE @i <= 1000000

BEGIN

 SET @a = dbo.fn_ImpCast(N'123456');

 SET @i = @i + 1;

END

ÏÂÃæµÄ´úÂëµ÷ÓÃfn_ExpCastº¯Êý, ÔËÐÐÁË17Ãë:

DECLARE @a AS NVARCHAR(4000);

DECLARE @i AS INT;

SET @i = 1;

WHILE @i <= 1000000

BEGIN

 SET @a = dbo.fn_ExpCast(N'123456');

 SET @i = @i + 1;

END

ÈçÄãËù¼û£¬²î±ð²»ÊǺÜÃ÷ÏÔ£¬ÔÚÕâ¸ö²âÊÔÖÐÒþʽת»»·½·¨ÉõÖÁ»¹Òª±ÈÏÔʽת»»·½·¨ÉÔ¿ìһЩ¡£

Íê³Éºó£¬ÔËÐÐÏÂÃæµÄ´úÂë½øÐÐÇåÀí¡£

IF OBJECT_ID('dbo.fn_ImpCast') IS NOT NULL

  DROP FUNCTION dbo.fn_ImpCast;

GO

IF OBJECT_ID('dbo.fn_ExpCast') IS NOT NULL

  DROP FUNCTION dbo.fn_ExpCast;

SQLÇ©Ãû(SQL Signature)

ÕâÒ»½ÚÌṩһ¸öº¯ÊýµÄT-SQLºÍCLRÁ½ÖÖʵÏÖ£¬¸Ãº¯Êý·µ»Ø²éѯ×Ö·û´®µÄÇ©Ãû¡£Ë¼Â·ÊǽÓÊÕ²éѯ×Ö·û´®×÷ΪÊäÈë²¢·µ»Ø±íʾ¸Ã²éѯ¡°Ç©Ãû¡±»ò¡°Ä£°å¡±µÄ×Ö·û´®¡£ÔÚÕâ¸öÇ©ÃûÖУ¬³öÏÖÔÚÊäÈë²éѯ×Ö·û´®ÖеÄËùÓÐ×ÖÃæÖµ£¨literal£©¶¼±»Ì滻Ϊһ¸öͨÓõķûºÅ£¨ÔÚÕâ¸öÀý×ÓÖÐÊÇ# £©¡£ÀýÈ磬¼ÙÉèÄãʹÓÃÏÂÃæµÄ²éѯ×Ö·û´®¡£

N'SELECT * FROM dbo.T1 WHERE col1 = 3 AND col2 > 78;'

ÄãÏ£ÍûµÃµ½ÏÂÃæµÄ×Ö·û´®£º

N'SELECT * FROM dbo.T1 WHERE col1 = # AND col2 > #'

µ±Äã°Ñ¸ú×Ùµ½µÄSQLÓï¾ä²åÈëÒ»¸ö±íºóÔÙͨ¹ýÕâЩÊý¾ÝÀ´Í³¼Æ²éѯµÄÐÔÄÜʱ£¬ÕâÑùµÄº¯Êý»á·Ç³£ÓÐÓá£Èç¹ûÄãÖ±½Ó°´Ô­Ê¼²éѯ×Ö·û´®·Ö×飬Âß¼­ÉÏÏàͬµÄ²éѯ»á±»·Åµ½²»Í¬µÄ×éÖС£Í³¼ÆÕâЩ²éѯǩÃûµÄÐÔÄܽ«ÎªÄãÌṩ¸üʵÓøüÓмÛÖµµÄÐÅÏ¢¡£

T-SQL SQLÇ©ÃûUDF

Äã¿ÉÒÔÔÚ´úÂëÇåµ¥6-2ÖÐÕÒµ½SQLÇ©Ãûº¯ÊýµÄT-SQLʵÏÖ¡£ÎÒÒª¸ÐлStuart Ozer£¬ÊÇËû±àдÁËÕâ¸öº¯Êý£¬²¢ÔÊÐíÎÒÔÚÕâ±¾ÊéÖÐʹÓá£StuartÊÇMicrosoft SQL Server Customer Advisory TeamµÄ³ÉÔ±¡£

´úÂëÇåµ¥6-2  ´´½¨fn_SQLSigTSQL UDFµÄ½Å±¾

IF OBJECT_ID('dbo.fn_SQLSigTSQL') IS NOT NULL

  DROP FUNCTION dbo.fn_SQLSigTSQL;

GO

CREATE FUNCTION dbo.fn_SQLSigTSQL

  (@p1 NTEXT, @parselength INT = 4000)

RETURNS NVARCHAR(4000)

--

--¸Ãº¯ÊýÒÔ¡°ÏÖ×´¡±ÌṩÇÒûÓÐÈκε£±£

--ͬʱҲûÓÐÊÚÓèÈκÎȨÀû -- ʹÓøú¯ÊýËù°üº¬µÄ½Å±¾Ê¾ÀýÊÜÏÂÁÐÌõ¿îÔ¼Êø

-- http://www.microsoft.com/info/cpyright.htm

--

-- ·Ö½â²éѯ×Ö·û´®

AS

BEGIN

  DECLARE @pos AS INT;

  DECLARE @mode AS CHAR(10);

  DECLARE @maxlength AS INT;

  DECLARE @p2 AS NCHAR(4000);

  DECLARE @currchar AS CHAR(1), @nextchar AS CHAR(1);

  DECLARE @p2len AS INT;

  SET @maxlength = LEN(RTRIM(SUBSTRING(@p1,1,4000)));

  SET @maxlength = CASE WHEN @maxlength > @parselength

                     THEN @parselength ELSE @maxlength END;

  SET @pos = 1;

  SET @p2 = '';

  SET @p2len = 0;

  SET @currchar = '';

  set @nextchar = '';

  SET @mode = 'command';

  WHILE (@pos <= @maxlength)

  BEGIN

    SET @currchar = SUBSTRING(@p1,@pos,1);

    SET @nextchar = SUBSTRING(@p1,@pos+1,1);

    IF @mode = 'command'

    BEGIN

      SET @p2 = LEFT(@p2,@p2len) + @currchar;

      SET @p2len = @p2len + 1 ;

      IF @currchar IN (',','(',' ','=','<','>','!')

        AND @nextchar BETWEEN '0' AND '9'

      BEGIN

        SET @mode = 'number';

        SET @p2 = LEFT(@p2,@p2len) + '#';

        SET @p2len = @p2len + 1;

      END

      IF @currchar = ''''

      BEGIN

        SET @mode = 'literal';

        SET @p2 = LEFT(@p2,@p2len) + '#''';

        SET @p2len = @p2len + 2;

      END

    END

    ELSE IF @mode = 'number' AND @nextchar IN (',',')',' ','=','<','>','!')

      SET @mode= 'command';

    ELSE IF @mode = 'literal' AND @currchar = ''''

      SET @mode= 'command';

    SET @pos = @pos + 1;

  END

  RETURN @p2;

END

GO

fn_SQLSigTSQLº¯Êý½ÓÊÕÁ½¸öÊäÈë²ÎÊý£º@p1ÊÇÊäÈëµÄ²éѯ×Ö·û´®£¬@parselengthÊÇÄãÒª·ÖÎöµÄ×î´ó×Ö·û¸öÊý¡£Èç¹û @parselengthСÓÚ @p1ÖеIJéѯ×Ö·û´®µÄ³¤¶È£¬º¯Êý½«Ö»·ÖÎö×î×ó±ßµÄ @parselength¸ö×Ö·û¡£¸Ãº¯ÊýÒ»´Î±éÀú×Ö·û´®ÖеÄÒ»¸ö×Ö·û¡£ÔÚ @mode±äÁ¿±£´æÒ»¸ö״ֵ̬£¬¸Ã±äÁ¿¿ÉÄÜÊÇÏÂÁÐÖµÖ®Ò»£º¡®command¡¯¡¢¡®number¡¯ »ò ¡®literal¡¯¡£

CommandÊÇĬÈϵÄ״̬£¬Ëü±íʾµ±Ç°µÄ×Ö·û½«±»´®Áªµ½Êä³ö×Ö·û´®ÖС£Number±íʾʶ±ð³öÒ»¸öÊý×Ö×ÖÃæÖµ£¨number literal£©£¬Õâʱ½«´®Áª# ·ûºÅ¡£µ±¶ººÅ¡¢×óÀ¨ºÅ¡¢¿Õ¸ñ»òÔËËã·ûºóÃæ¸úÒ»¸öÊý×Öʱ±êʶһ¸öÊý×Ö×ÖÃæÖµ¡£µ±ÏÂÒ»¸ö×Ö·ûÊǶººÅ¡¢ÓÒÀ¨ºÅ¡¢¿Õ¸ñ»òÔËËã·ûʱ״̬´ÓNumberתµ½Command¡£Literal±íʾ±êʶÁËÒ»¸ö×Ö·û´®×ÖÃæÖµ, Õâʱ½«´®Áª×Ö·û´®' # '¡£µ±¼ì²âµ½×óÒýºÅʱ±êʶһ¸ö×Ö·û´®×ÖÃæÖµ¡£µ±¼ì²âµ½ÓÒÒýºÅʱ״̬´Óliteralתµ½command¡£

Òª²âÊÔfn_SQLSigTSQLº¯Êý£¬ÔËÐÐÏÂÃæµÄ´úÂ룺

SELECT dbo.fn_SQLSigTSQL

  (N'SELECT * FROM dbo.T1 WHERE col1 = 3 AND col2 > 78', 4000);

Êä³öÈçÏ£º

SELECT * FROM dbo.T1 WHERE col1 = # AND col2 > #

CLR SQL Ç©Ãû UDF

´úÂëÇåµ¥6-3ºÍ6-4°üº¬ÁËSQLÇ©Ãûº¯ÊýµÄC# ºÍ Visual BasicʵÏÖ¡£¸Ãº¯ÊýµÄ .NET°æ±¾¸Ä±à×ÔStuartµÄËã·¨¡£ÓÉAndrew J. Kelly ºÍ Dejan Sarka¿ª·¢£¬ËûÃǶ¼ÊÇSolid Quality LearningµÄ¹ËÎʺÍÖøÃûµÄSQL Server MVP¡£¸Ãº¯ÊýµÄ .NET°æ±¾Óë´úÂëÇåµ¥6-2ÖеÄT-SQL°æ±¾ÏàËÆ£¬Ìṩ¸Ã°æ±¾Ö»ÊÇΪÁËÐÔÄܲâÊԺͱȽ϶øÒÑ¡£ÔÚ±¾ÕµĺóÃæ£¬ÎÒ½«ÃèÊöʹÓÃÕýÔò±í´ïʽÉú³É²éѯǩÃûµÄ¸üΪǿ´óµÄ»ùÓÚCLRµÄ½â¾ö·½°¸¡£

´úÂëÇåµ¥6-3  C# °æµÄfn_SQLSigCLRº¯Êý

// SQL Ç©Ãû

[SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.None)]

public static SqlString fn_SQLSigCLR(SqlString inpRawString,

  SqlInt32 inpParseLength)

{

    if (inpRawString.IsNull)

        return SqlString.Null;

    int pos = 0;

    string mode = "command";

    string RawString = inpRawString.Value;

    int maxlength = RawString.Length;

    StringBuilder p2 = new StringBuilder();

    char currchar = ' ';

    char nextchar = ' ';

    int ParseLength = RawString.Length;

    if (!inpParseLength.IsNull)

        ParseLength = inpParseLength.Value;

    if (RawString.Length > ParseLength)

    {

        maxlength = ParseLength;

    }

    while (pos < maxlength)

    {

        currchar = RawString[pos];

        if (pos < maxlength - 1)

        {

            nextchar = RawString[pos + 1];

        }

        else

        {

            nextchar = RawString[pos];

        }

        if (mode == "command")

        {

            p2.Append(currchar);

            if ((",( =<>!".IndexOf(currchar) >= 0)

               &&

                (nextchar >= '0' && nextchar <= '9'))

            {

                mode = "number";

                p2.Append('#');

            }

            if (currchar == '\'')

            {

                mode = "literal";

                p2.Append("#'");

            }

        }

        else if ((mode == "number")

                  &&

                   (",( =<>!".IndexOf(nextchar) >= 0))

        {

            mode = "command";

        }

        else if ((mode == "literal") && (currchar == '\''))

        {

            mode = "command";

        }

        pos++;

    }

    return p2.ToString ();

}

´úÂëÇåµ¥6-4  Visual Basic°æµÄfn_SQLSigCLRº¯Êý

' SQL Ç©Ãû

<SqlFunction(IsDeterministic:=True, DataAccess:=DataAccessKind.None)> _

Public Shared Function fn_SQLSigCLR(ByVal inpRawString As SqlString, _

  ByVal inpParseLength As SqlInt32) As SqlString

    If inpRawString.IsNull Then

        Return SqlString.Null

    End If

    Dim pos As Integer = 0

    Dim mode As String = "command"

    Dim RawString As String = inpRawString.Value

    Dim maxlength As Integer = RawString.Length

    Dim p2 As StringBuilder = New StringBuilder()

    Dim currchar As Char = " "c

    Dim nextchar As Char = " "c

    Dim ParseLength As Integer = RawString.Length

    If (Not inpParseLength.IsNull) Then

        ParseLength = inpParseLength.Value

    End If

    If (RawString.Length > ParseLength) Then

        maxlength = ParseLength

    End If

    While (pos < maxlength)

        currchar = RawString(pos)

        If (pos < maxlength - 1) Then

            nextchar = RawString(pos + 1)

        Else

            nextchar = RawString(pos)

        End If

        If (mode = "command") Then

            p2.Append(currchar)

            If ((",( =<>!".IndexOf(currchar) >= 0) _

               And _

                (nextchar >= "0"c And nextchar <= "9"c)) Then

                mode = "number"

                p2.Append("#")

            End If

            If (currchar = "'"c) Then

                mode = "literal"

                p2.Append("#")

            End If

        ElseIf ((mode = "number") And _

                (",( =<>!".IndexOf(nextchar) >= 0)) Then

            mode = "command"

        ElseIf ((mode = "literal") And _

                (currchar = "'"c)) Then

            mode = "command"

        End If

        pos=pos+1

    End While

    Return p2.ToString

End Function

ʹÓÃÏÂÃæµÄ´úÂë×¢²áC# °æfn_SQLSigCLRº¯Êý£º

IF OBJECT_ID('dbo.fn_SQLSigCLR') IS NOT NULL

  DROP FUNCTION dbo.fn_SQLSigCLR;

GO

CREATE FUNCTION dbo.fn_SQLSigCLR

  (@rawstring AS NVARCHAR(4000), @parselength AS INT)

RETURNS NVARCHAR(4000)

EXTERNAL NAME CLRUtilities.CLRUtilities.fn_SQLSigCLR;

Èç¹ûÄãʹÓÃVisual BasicʵÏָú¯Êý£¬Ê¹ÓÃÏÂÃæµÄ´úÂë½øÐÐ×¢²á£º

CREATE FUNCTION dbo.fn_SQLSigCLR

  (@rawstring AS NVARCHAR(4000), @parselength AS INT)

RETURNS NVARCHAR(4000)

EXTERNAL NAME CLRUtilities.[CLRUtilities.CLRUtilities].fn_SQLSigCLR;

ÔËÐÐÏÂÃæµÄ´úÂë²âÊÔfn_SQLSigCLRº¯Êý£º

SELECT dbo.fn_SQLSigCLR

  (N'SELECT * FROM dbo.T1 WHERE col1 = 3 AND col2 > 78', 4000);

µÃµ½µÄÊä³öÈçÏ£º

SELECT * FROM dbo.T1 WHERE col1 = # AND col2 > #

±È½ÏT-SQL ºÍ CLR SQL Ç©Ãû UDFµÄÐÔÄÜ

ÔÚ×Ö·û´®´¦Àí·½Ãæ .NET´úÂë±ÈT-SQL¸ü¿ì¡£SQLÇ©Ãûº¯Êý¾ÍÊÇÒ»¸ö¿ÉÒÔÑÝʾÕâÖÖÐÔÄܲîÒìµÄ¼«ºÃµÄÀý×Ó£¬ÓÈÆäÊÇÁ½¸ö°æ±¾ÊµÏÖµÄÊÇͬһ¸öËã·¨¡£ÄãÂíÉϾͻῴµ½ËüÃÇÔÚ×Ö·û´®´¦Àí·½ÃæµÄÐÔÄܲîÒì¡£

Ê×ÏÈ£¬ÔËÐÐÏÂÃæµÄ´úÂë´´½¨Queries±í²¢ÓÃ100 000¸ö²éѯ×Ö·û´®Ìî³ä¸Ã±í£º

IF OBJECT_ID('dbo.Queries') IS NOT NULL

  DROP TABLE dbo.Queries;

GO

SELECT CAST(N'SELECT * FROM dbo.T1 WHERE col1 = 3 AND col2 > 78'

         AS NVARCHAR(MAX)) AS query

INTO dbo.Queries

FROM dbo.Nums

WHERE n <= 100000;

´ò¿ªSSMSÖеÄÖ´Ðкó·ÅÆú½á¹ûÑ¡Ïî¡£

µ±ÎÒÔËÐÐÏÂÃæÕâÐÐʹÓÃÁËT-SQL°æº¯ÊýµÄ´úÂëʱ£¬ÓÃÁ˽«½ü100Ãë¡£

SELECT dbo.fn_SQLSigTSQL(query, 4000) FROM dbo.Queries;

¶ø¸Ãº¯ÊýµÄCLR C# °æÔÚ1ÃëÖÓÖ®ÄÚ¾ÍÍê³ÉÁË£¬Visual Basic°æÓÃÁË2ÃëÖÓ¡£

SELECT dbo.fn_SQLSigCLR(query, 4000) FROM dbo.Queries;

¹Ø±ÕSSMSÉϵÄÖ´Ðкó·ÅÆú½á¹ûÑ¡Ïî¡£

ÈçÄãËù¼û£¬¸Ãº¯ÊýµÄCLR°æ±¾´ó¸Å±ÈT-SQL°æ±¾¿ì100±¶¡£

¾ÍÏñÎÒÔøÌáµ½µÄ£¬fn_SQLSigCLRº¯ÊýʵÏÖµÄËã·¨ºÍfn_SQLSigTSQLº¯ÊýÏàͬ£¬ÌṩËüÖ»ÊÇΪÁËÐÔÄܱȽϡ£Äã¿ÉÒÔʹÓÃÕýÔò±í´ïʽʵÏÖ¸üΪǿ´óµÄ»ùÓÚCLRµÄ½â¾ö·½°¸¡£ÎÒÒÔÇ°ÔøÏòÄãչʾ¹ýÈçºÎʹÓÃÕýÔò±í´ïʽ½øÐÐģʽƥÅ䣬ËüÓÃÓÚ¼ì²éÒ»¸ö×Ö·û´®ÊÇ·ñÆ¥Åäijģʽ¡£ÄãÒ²¿ÉÒÔʹÓÃÕýÔò±í´ïʽʵÏÖ»ùÓÚģʽ£¨pattern-based£©µÄÌæ»»¡£¼´£¬Äã¿ÉÒÔʹÓÃÒ»¸öÄ£Ê½Ìæ»»×Ö·û´®ÖгöÏֵįäËûģʽ¡£ÏÂÃæÊÇfn_RegExReplaceº¯ÊýµÄC# ¶¨Ò壬Ëüµ÷ÓÃRegex¶ÔÏóµÄReplace·½·¨£º

// fn_RegExReplace ¨C»ùÓÚÕýÔò±í´ïʽµÄͨÓÃÌæ»»

[SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.None)]

public static SqlString fn_RegExReplace(

    SqlString input, SqlString pattern, SqlString replacement)

{

    if (input.IsNull || pattern.IsNull || replacement.IsNull)

        return SqlString.Null;

    else

        return (SqlString)Regex.Replace(

        input.Value, pattern.Value, replacement.Value);

}

ÏÂÃæÊǸú¯ÊýµÄVisual Basic¶¨Ò壺

' fn_RegExReplace -»ùÓÚÕýÔò±í´ïʽµÄͨÓÃÌæ»»

<SqlFunction(IsDeterministic:=True, DataAccess:=DataAccessKind.None)> _

Public Shared Function fn_RegExReplace( _

  ByVal input As SqlString, ByVal pattern As SqlString, _

  ByVal replacement As SqlString) As SqlString

    If (input.IsNull Or pattern.IsNull Or replacement.IsNull) Then

        Return SqlString.Null

    Else

        Return CType(Regex.Replace( _

            input.Value, pattern.Value, replacement.Value), SqlString)

    End If

End Function

¸Ãº¯Êý½ÓÊÕÈý¸öÊäÈë²ÎÊý£ºinput¡¢patternºÍreplacement¡£º¯ÊýÊ×Ïȼì²é²ÎÊýÖµÊÇ·ñΪNull£¬Èç¹ûÊÇÔò·µ»ØNull¡£Èç¹û²ÎÊýÖµ¶¼²»ÎªNull£¬Ôòº¯Êýµ÷ÓÃRegex.Replace·½·¨£¬¸Ã·½·¨ÓÃreplacementÄ£Ê½Ìæ»»input×Ö·û´®ÄÚ³öÏÖµÄÿ¸öpattern¡£ÏÂÃæÎÒÀ´ÑÝʾÈçºÎʹÓÃfn_RegExReplaceº¯ÊýÉú³É²éѯǩÃû£¬µ±È»ÄãÒ²¿ÉÒ԰Ѹú¯ÊýÓÃÓÚÆÕͨµÄ»ùÓÚģʽµÄ×Ö·û´®Ìæ»»¡£

ʹÓÃÏÂÃæµÄ´úÂë×¢²áC# °æµÄfn_RegExReplaceº¯Êý¡£

IF OBJECT_ID('dbo.fn_RegExReplace') IS NOT NULL

  DROP FUNCTION dbo.fn_RegExReplace;

GO

CREATE FUNCTION dbo.fn_RegExReplace(

  @input       AS NVARCHAR(MAX),

  @pattern     AS NVARCHAR(MAX),

  @replacement AS NVARCHAR(MAX))

RETURNS NVARCHAR(MAX)

WITH RETURNS NULL ON NULL INPUT

EXTERNAL NAME CLRUtilities.CLRUtilities.fn_RegExReplace;

Èç¹ûÄãÓÃVisual BasicʵÏָú¯Êý£¬Ê¹ÓÃÏÂÃæµÄ´úÂë½øÐÐ×¢²á¡£

CREATE FUNCTION dbo.fn_RegExReplace(

  @input       AS NVARCHAR(MAX),

  @pattern     AS NVARCHAR(MAX),

  @replacement AS NVARCHAR(MAX))

RETURNS NVARCHAR(MAX)

WITH RETURNS NULL ON NULL INPUT

EXTERNAL NAME CLRUtilities.[CLRUtilities.CLRUtilities].fn_RegExReplace;

ÏÂÃæÊÇÒ»¸öʾÀý£¬ËüÑÝʾÁËÈçºÎʹÓøú¯ÊýΪQueries±íÖвéѯ×Ö·û´®µÄÉú³É²éѯǩÃû¡£

SELECT

  dbo.fn_RegExReplace(query,

    N'([\s,(=<>!](?![^\]]+[\]]))(?:(?:(?:(?#   expression coming

     )(?:([N])?('')(?:[^'']|'''')*(''))(?#     character

     )|(?:0x[\da-fA-F]*)(?#                    binary

     )|(?:[-+]?(?:(?:[\d]*\.[\d]*|[\d]+)(?#    precise number

     )(?:[eE]?[\d]*)))(?#                      imprecise number

     )|(?:[~]?[-+]?(?:[\d]+))(?#               integer

     ))(?:[\s]?[\+\-\*\/\%\&\|\^][\s]?)?)+(?#  operators

     ))',

    N'$1$2$3#$4')

FROM dbo.Queries;

½áºÏÄÚÖõÄ×¢ÊÍ£¬ÕâЩģʽºÜÈÝÒ×Àí½â¡£ËüÄÜʶ±ð£¨²¢ÓÃ#·ûºÅÌæ»»£©±Èfn_SQLSigCLRº¯Êý¸ü¶àµÄ×ÖÃæÖµÀàÐÍ¡£Ëü¿ÉÒÔʶ±ð×Ö·û×ÖÃæÖµ¡¢¶þ½øÖÆ×ÖÃæÖµ¡¢¾«È·Êý×Ö¡¢½üËÆÊý×Ö£¬ÉõÖÁ¿ÉÒÔʶ±ð°üº¬×ÖÃæÖµµÄ»ìºÏ±í´ïʽ£¨fold expression£©£¬²¢ÓÃ#·ûºÅÌæ»»ËüÃÇ¡£Ïà¶ÔÓÚfn_SQLSigCLRº¯Êý£¬¸Ã½â¾ö·½°¸»¹ÓÐÒ»¸öÓÅÊÆ£¬Äã¿ÉÒÔά»¤×Ô¼ºµÄÕýÔò±í´ïʽ²¢ÔöÇ¿ËüÃǵŦÄÜÒÔÖ§³Ö¸ü¶àµÄÇé¿ö£¬¶øÇÒ²»ÐèÒªÐ޸ĸú¯ÊýµÄ¶¨Ò塣Ȼ¶ø£¬Í¨¹ýÕýÔò±í´ïʽËùÔöÇ¿µÄ¹¦ÄÜÐèÒªÒ»¶¨µÄ³É±¾£¬ÉÏÃæµÄ²éѯ´ó¸Å»áÔËÐÐ12Ã룬±Èfn_SQLSigCLRº¯ÊýÂýÁË12±¶£¬µ«»¹ÊDZÈfn_SQLSigTSQLº¯Êý¿ì8±¶¡£

Ìáʾ    Äã¿ÉÄÜÏë´´½¨Ò»Ð©¾ßÓиü¹ã·ºÓÃ;µÄº¯Êý£¬±ÈÈç,²»ÓÃΪº¯ÊýÃû³ÆÏÞ¶¨Êý¾Ý¿â(CLRUtilities.dbo.fn_RegExReplace)¾Í¿ÉÒÔÔÚËùÓÐÊý¾Ý¿âÖзÃÎÊfn_RegExReplace¡£Îª´Ë£¬ÔÚÿ¸öҪʹÓøú¯ÊýµÄÊý¾Ý¿âÖд´½¨Ò»¸ö¸Ãº¯ÊýµÄͬÒå´Ê(synonym)£¬ÎªÁËÄÜÔÚNorthwindÊý¾Ý¿âÖÐʹÓøú¯Êý£¬ÔËÐÐÏÂÃæµÄ´úÂ룺

            USE Northwind;
GO
CREATE SYNONYM dbo.fn_RegExReplace
  FOR CLRUtilities.dbo.fn_RegExReplace;

            Èç¹ûÄãÔÚmodelÊý¾Ý¿â´´½¨ÁËÒ»¸öͬÒå´Ê£¬ÒÔºóÄã´´½¨µÄÿ¸öÐÂÊý¾Ý¿â¶¼»á´´½¨Õâ¸öͬÒå´Ê£¬ÒòΪÐÂÊý¾Ý¿â¶¼ÊÇÒÔmodel¸±±¾µÄ·½Ê½´´½¨µÄ¡£ÕâͬÑùÒ²Ó¦ÓÃÓÚtempdbÊý¾Ý¿â£¬ËüÔÚÿ´ÎÖØÆô¶¯SQL Serverʱ±»´´½¨¡£

Íê³Éºó£¬ÔËÐÐÏÂÃæµÄ´úÂë½øÐÐÇåÀí¡£

USE Northwind;

GO

IF OBJECT_ID('dbo.fn_RegExReplace', 'SN') IS NOT NULL

  DROP SYNONYM dbo.fn_RegExReplace;

GO

USE CLRUtilities;

GO

IF OBJECT_ID('dbo.fn_SQLSigTSQL') IS NOT NULL

  DROP FUNCTION dbo.fn_SQLSigTSQL;

GO

IF OBJECT_ID('dbo.fn_SQLSigCLR') IS NOT NULL

  DROP FUNCTION dbo.fn_SQLSigCLR;

GO

IF OBJECT_ID('dbo.fn_RegExReplace') IS NOT NULL

  DROP FUNCTION dbo.fn_RegExReplace;

GO

¡¾²é¿´ËùÓÐÆÀÂÛ(0)Ìõ¡¿

×î½üÆÀÂÛ



ÕýÔÚÔØÈëÆÀÂÛÁбí...
ÈȵãÆÀÂÛ