SQL Server T-SQL'de normal ifadeler


127

SPSQL Server için T-SQL'de yazılmış (CLR yok, genişletilmiş , saf T-SQL yok) ve paylaşılan barındırma ile çalışması gereken herhangi bir normal ifade kitaplığı var mı ?

Düzenle:

  • Teşekkürler, ben biliyorum PATINDEX, LIKE, xp_ spsve CLR çözümleri
  • Ayrıca regex için en iyi yer olmadığını da biliyorum, soru teorik :)
  • Azaltılmış işlevsellik de kabul edilir

2
Benim de bu sorum var. Bir veritabanının buna sahip olmak için en iyi yer olmadığını biliyorum, ancak gerçek şu ki, diğer çözümler sunucuyu yeniden yapılandırmak için SQL yönetici izinleri gerektiriyor. Maalesef, müşterilerimizden bazıları CLR vb.'yi etkinleştirmeyi seçmeyecekler ve bizler yalnızca veritabanı çözümlerine bağlı kaldık.
Paul Draper

@PaulDraper ve xnagyg: SQLCLR neden dışlansın? Sorgularda Normal İfadeler almanın en uygun yoludur. Ve neden müşterilerinizden bazıları CLR'yi etkinleştirmemeyi seçsin? Henüz geçerli bir nedene rastlamadım . Elbette, "güvenlik" ve "performans" ı duyuyorum, ancak bunlar SQLCLR'nin nasıl çalıştığını ve nasıl kısıtlanabileceğini anlamamamızın bir sonucu olan sahte nedenler.
Solomon Rutzky

3
@srutzky: çoğu paylaşılan barındırma sağlayıcısı CLR'ye izin vermiyor. Onlara "güvenlik" ve "performans" hakkında sorular sormalısınız :)
xnagyg

@xnagyg Elbette, birkaç tane sorabilirim. Ancak, bir grubun davranışına işaret etmek, bu davranış için " geçerli bir neden var mı" sorusunu hiçbir şekilde ele almaz . Tüm bu paylaşılan barındırma sağlayıcılarının politikalarını aynı yanlış anlamaya dayalı olarak belirlemesi de aynı kolaylık olabilir. Ve hiçbir şey olmasa bile, hepsinin SQLCLR'ye izin vermemesi , aslında bir problem olma fikrinden daha fazla bir problem olmadığı fikrini desteklemektedir, çünkü bu problemler var olsaydı, SQLCLR'ye izin veren sağlayıcılar yaşardı. bu sorunlar ve buna izin vermeyi bırakır.
Solomon Rutzky

@xnagyg Ayrıca, SAFEya EXTERNAL_ACCESSda olarak işaretlenmiş ve işaretlenmemiş Meclisler açısından konuştuğumu açıklığa kavuşturmalıyım UNSAFE(bu 2 İzin Kümesinin paylaşılan bir barındırma ortamı için neden sorunlu olduğunu anladığım gibi). Paylaşılan bir ortam olan Microsoft Azure SQL Veritabanı V12 (yani 2014 sonundan itibaren yeni sürüm), olarak işaretlenen SAFE(ve FROM 0x...DLL yükleyemediğiniz için DLL yerine yüklenen) Montajlara izin verir . Ancak SAFEDüzenli İfadeler ve diğer çok kullanışlı işlevlerin LOTS için gereken tek şey budur.
Solomon Rutzky

Yanıtlar:


78

PATINDEX işlevi nasıl olur ?

TSQL'deki kalıp eşleştirme tam bir düzenli ifade kitaplığı değildir, ancak size temel bilgileri verir.

(Çevrimiçi Kitaplardan)

Wildcard  Meaning  
% Any string of zero or more characters.

_ Any single character.

[ ] Any single character within the specified range 
    (for example, [a-f]) or set (for example, [abcdef]).

[^] Any single character not within the specified range 
    (for example, [^a - f]) or set (for example, [^abcdef]).

7
En az on yıldır (SQL Server 2005+) LIKEher şeyi desteklemiştir PATINDEX. Bundan öncesini bilmiyorum ...
TJ Crowder

1
Yine de bu, örneğin değişken sayıda ascii harfiyle eşleşen bir kalıp belirlememe izin vermiyor. %0 veya daha fazla karakterle (ne olursa olsun) [...]eşleşir, yalnızca biriyle eşleşir ve arada hiçbir şey yoktur.
Martijn Pieters

LIKE, PATINDEX> 0
Reversed Engineer ile

21

CLR ile regex kullanmakla ilgilenen varsa, işte bir çözüm. Aşağıdaki fonksiyon (C # .net 4.5), model eşleşirse 1 ve eşleşmezse 0 döndürür. Alt sorgularda satırları etiketlemek için kullanıyorum. SQLfunction özniteliği sql sunucusuna bu yöntemin SQL sunucusunun kullanacağı asıl UDF olduğunu söyler. Dosyayı, yönetim stüdyosundan erişebileceğiniz bir yere dll olarak kaydedin.

// default using statements above
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;

namespace CLR_Functions
{   
    public class myFunctions
    {
        [SqlFunction]
        public static SqlInt16 RegexContain(SqlString text, SqlString pattern)
        {            
            SqlInt16 returnVal = 0;
            try
            {
                string myText = text.ToString();
                string myPattern = pattern.ToString();
                MatchCollection mc = Regex.Matches(myText, myPattern);
                if (mc.Count > 0)
                {
                    returnVal = 1;
                }
            }
            catch
            {
                returnVal = 0;
            }

            return returnVal;
        }
    }
}

Yönetim stüdyosunda dll dosyasını programlanabilirlik - montajlar - yeni montaj yoluyla içe aktarın

Ardından şu sorguyu çalıştırın:

CREATE FUNCTION RegexContain(@text NVARCHAR(50), @pattern NVARCHAR(50))
RETURNS smallint 
AS
EXTERNAL NAME CLR_Functions.[CLR_Functions.myFunctions].RegexContain

Ardından, montajı içinde sakladığınız veritabanı aracılığıyla işleve tam erişiminiz olmalıdır.

Daha sonra aşağıdaki gibi sorgularda kullanın:

SELECT * 
FROM 
(
    SELECT
        DailyLog.Date,
        DailyLog.Researcher,
        DailyLog.team,
        DailyLog.field,
        DailyLog.EntityID,
        DailyLog.[From],
        DailyLog.[To],
        dbo.RegexContain(Researcher, '[\p{L}\s]+') as 'is null values'
    FROM [DailyOps].[dbo].[DailyLog]
) AS a
WHERE a.[is null values] = 0

14

LIKE kullanılarak kullanılabilen bazı temel kalıp eşleştirmesi vardır, burada% herhangi bir sayı ve karakter kombinasyonuyla eşleşir, _ herhangi bir karakterle eşleşir ve [abc] a, b veya c ile eşleşebilir. MSDN sitesinde daha fazla bilgi var .


5

Eğer SQL Server 2016 veya üzeri kullanıyorsanız, kullanabileceğiniz sp_execute_external_scriptBöyle olarak Normal İfade aramalar için de fonksiyonları vardır R. ile birlikte grepve grepl.

İşte e-posta adresleri için bir örnek. SQL Server veritabanı motoru aracılığıyla bazı "kişileri" sorgulayacağım, bu kişilerin verilerini R'ye ileteceğim, hangi kişilerin geçersiz e-posta adreslerine sahip olduğuna R'nin karar vermesine izin vereceğim ve R'nin bu kişi alt kümesini SQL Server'a geri vermesini sağlayacağım. "Kişiler" örnek veritabanındaki [Application].[People]tablodan [WideWorldImporters]. Adlandırılmış bir veri çerçevesi olarak R motoruna aktarılırlar InputDataSet. R, hangi kişilerin RegEx dizesi arama düzeniyle eşleşmeyen e-posta adreslerine sahip olduğunu bulmak için grepl işlevini "değil" operatörüyle (ünlem işareti!) Kullanır.

EXEC sp_execute_external_script 
 @language = N'R',
 @script = N' RegexWithR <- InputDataSet;
OutputDataSet <- RegexWithR[!grepl("([_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,4}))", RegexWithR$EmailAddress), ];',
 @input_data_1 = N'SELECT PersonID, FullName, EmailAddress FROM Application.People'
 WITH RESULT SETS (([PersonID] INT, [FullName] NVARCHAR(50), [EmailAddress] NVARCHAR(256)))

Uygun özelliklerin SQL Server ana bilgisayarına yüklenmesi gerektiğini unutmayın. SQL Server 2016 için buna "SQL Server R Hizmetleri" denir. SQL Server 2017 için, "SQL Server Machine Learning Services" olarak yeniden adlandırıldı.

Kapanış Düşünceleri Microsoft'un SQL (T-SQL) uygulamasının RegEx için yerel desteği yoktur. Önerilen bu çözüm, OP için CLR saklı yordamın kullanımından daha fazla arzu edilmeyebilir. Ancak, soruna yaklaşmak için ek bir yol sunar.


4

Hala bu soruya bakan biri varsa, http://www.sqlsharp.com/ veritabanınıza düzenli ifadeli CLR işlevleri eklemenin ücretsiz ve kolay bir yoludur .


3
Bir kez daha, bir CLR çözümüyüm - OP'nin istediği şey değil
Reversed Engineer

10
@DaveBoltman: Soruyu 2008'de sordu. İnsanlar bazen bunu arıyor ve CLR'den kaçınmak istemeden bu soruyla karşılaşıyor. Bu bana yardımcı oldu ve onlara yardımcı olabilir.
John Fisher

Elbette, sana katılıyorum @JohnFisher - bu , CLR kullanan biri için yararlı bir cevaptır. Ama 2015 yılında, biz OP yıl olsun :) Örneğin Aracın aküsü edildi vermez 2008 yılında yaptığı gibi çeşitli nedenlerle bizim SQL projesi (hiçbir CLR) SQL tek çare gibi yine olur yayınlandı 1859 . Ancak, 100 yıldan daha uzun bir süre sonra piyasaya sürülen NiMH piller gibi daha modern pilleri, çeşitli nedenlerle (örneğin bir arabayı alabilmek gibi) kullanmaktan yine de kaçınmak istersiniz
Reversed Engineer

2
@DaveBoltman: "İnsanların bazen bunu aradığı ve CLR'den kaçınmak istemeden bu soruyla karşılaştığı" bölümünü kaçırdınız. Kilit nokta buydu.
John Fisher

elbette - haklısın @JohnFisher, bunu söyledin. Size yardımcı olmasına sevindim ve eminim başkalarına da yardımcı olacaktır
Reversed Engineer

2

OLE Otomasyonunu kullanarak VBScript normal ifade özelliklerini kullanabilirsiniz. Bu, bir montaj oluşturma ve sürdürme ek yükünden çok daha iyidir. Ana olanın daha iyi değiştirilmiş bir sürümünü edinmek için lütfen yorumlar bölümünü incelediğinizden emin olun.

http://blogs.msdn.com/b/khen1234/archive/2005/05/11/416392.aspx

DECLARE @obj INT, @res INT, @match BIT;
DECLARE @pattern varchar(255) = '<your regex pattern goes here>';
DECLARE @matchstring varchar(8000) = '<string to search goes here>';
SET @match = 0;

-- Create a VB script component object
EXEC @res = sp_OACreate 'VBScript.RegExp', @obj OUT;

-- Apply/set the pattern to the RegEx object
EXEC @res = sp_OASetProperty @obj, 'Pattern', @pattern;

-- Set any other settings/properties here
EXEC @res = sp_OASetProperty @obj, 'IgnoreCase', 1;

-- Call the method 'Test' to find a match
EXEC @res = sp_OAMethod @obj, 'Test', @match OUT, @matchstring;

-- Don't forget to clean-up
EXEC @res = sp_OADestroy @obj;

Hata alırsanız SQL Server blocked access to procedure 'sys.sp_OACreate'..., sp_reconfigureetkinleştirmek için kullanın Ole Automation Procedures. (Evet, maalesef bu sunucu düzeyinde bir değişiklik!)

TestYöntem hakkında daha fazla bilgi burada mevcuttur

Mutlu kodlama


sry, bunun eski olduğunu biliyorum AMA: OLE aracılığıyla VBScript neden CLR'den "çok daha iyi"? YALNIZCA bakımı düşünüyorsanız, haklı OLABİLİRSİNİZ, AMA performans hakkında ne düşünüyorsunuz?
Swe

1
@swe 'Çok daha iyi' ile, sadece bu amaç için bir .NET derlemesi oluşturmanın ve sürdürmenin ek yükünden dolayı kazanılan zamandan bahsediyordum.
James Poulose
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.