SQL Server Ekspresi reguler dalam T-SQL

127

Apakah ada pustaka ekspresi reguler yang ditulis dalam T-SQL (tanpa CLR, tanpa extended SP, T-SQL murni) untuk SQL Server, dan itu harus bekerja dengan shared hosting?

Edit:

  • Terima kasih, aku tahu tentang PATINDEX, LIKE, xp_ spsdan solusi CLR
  • Saya juga tahu itu bukan tempat terbaik untuk regex, pertanyaannya adalah teoritis :)
  • Fungsi yang dikurangi juga diterima
xnagyg
sumber
2
Saya juga punya pertanyaan ini. Saya tahu bahwa database bukan tempat terbaik untuk memiliki ini, tetapi kenyataannya adalah bahwa solusi lain memerlukan izin admin SQL untuk mengkonfigurasi ulang server. Sayangnya, beberapa klien kami tidak akan memilih untuk mengaktifkan CLR, dll, dan kami terjebak pada solusi hanya untuk basis data.
Paul Draper
@ PaulDraper dan xnagyg: mengapa mengesampingkan SQLCLR? Ini adalah cara paling tepat untuk mendapatkan Ekspresi Reguler dalam kueri. Dan mengapa beberapa klien Anda memilih untuk tidak mengaktifkan CLR? Saya belum menemukan alasan yang valid . Tentu, saya mendengar "keamanan" dan "kinerja", tetapi itu adalah alasan palsu yang merupakan hasil dari tidak memahami bagaimana SQLCLR bekerja dan bagaimana hal itu dapat dibatasi.
Solomon Rutzky
3
@srutzky: sebagian besar penyedia hosting bersama tidak mengizinkan CLR. Anda harus bertanya kepada mereka tentang "keamanan" dan "kinerja" :)
xnagyg
@ xnagyg Tentu, saya bisa bertanya beberapa. Namun, menunjuk pada perilaku suatu kelompok tidak dengan cara apa pun menjawab pertanyaan "apakah ada alasan yang sah " untuk perilaku itu. Bisa saja dengan mudah bahwa semua penyedia hosting berbagi menetapkan kebijakan mereka berdasarkan kesalahpahaman yang sama. Dan, jika tidak ada yang lain, fakta sederhana bahwa tidak semua dari mereka melarang SQLCLR benar-benar mendukung gagasan tidak ada masalah lebih dari gagasan ada masalah karena jika masalah itu memang ada, penyedia yang memungkinkan SQLCLR akan mengalami masalah-masalah itu dan akan berhenti membiarkannya.
Solomon Rutzky
@xnagyg Juga, saya harus mengklarifikasi bahwa saya berbicara dalam hal Majelis yang ditandai sebagai SAFEdan tidak ditandai sebagai salah satu EXTERNAL_ACCESSatau UNSAFE(karena saya mengerti mengapa 2 Set Izin yang terakhir itu akan bermasalah untuk lingkungan hosting bersama). Microsoft Azure SQL Database V12 (yaitu versi baru pada akhir 2014), yang merupakan lingkungan bersama, memungkinkan untuk Sidang ditandai sebagai SAFE(dan dimuat melalui FROM 0x...bukan dari DLL karena Anda tidak dapat mengunggah DLL). Tetapi SAFEadalah semua yang diperlukan untuk Ekspresi Reguler dan BANYAK fungsi lainnya yang sangat berguna.
Solomon Rutzky

Jawaban:

77

Bagaimana dengan fungsi PATINDEX ?

Pencocokan pola dalam TSQL bukan pustaka regex lengkap, tetapi memberi Anda dasar-dasarnya.

(Dari Buku Daring)

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]).
Eric Z Beard
sumber
7
Selama setidaknya satu dekade (SQL Server 2005+), LIKEtelah mendukung semuanya PATINDEX. Tidak tahu tentang itu sebelumnya ...
TJ Crowder
1
Namun ini tidak membiarkan saya menentukan pola yang cocok, katakanlah, sejumlah variabel huruf ascii. %cocok dengan 0 atau lebih karakter (terlepas dari), [...]hanya cocok dengan satu, dan tidak ada di antara keduanya.
Martijn Pieters
LIKE adalah sama dengan PATINDEX> 0
Reversed Engineer
21

Jika ada yang tertarik menggunakan regex dengan CLR di sini adalah solusinya. Fungsi di bawah ini (C # .net 4.5) mengembalikan 1 jika polanya cocok dan 0 jika polanya tidak cocok. Saya menggunakannya untuk menandai baris di sub kueri. Atribut SQLfunction memberitahu sql server bahwa metode ini adalah UDF aktual yang akan digunakan oleh server SQL. Simpan file sebagai dll di tempat Anda dapat mengaksesnya dari studio manajemen.

// 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;
        }
    }
}

Di studio manajemen, impor file dll melalui programabilitas - rakitan - rakitan baru

Kemudian jalankan kueri ini:

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

Maka Anda harus memiliki akses lengkap ke fungsi melalui database tempat Anda menyimpannya.

Kemudian gunakan dalam pertanyaan seperti ini:

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
Matt Farguson
sumber
14

Ada beberapa pencocokan pola dasar yang tersedia melalui LIKE, di mana% cocok dengan angka dan kombinasi karakter apa pun, _ cocok dengan satu karakter apa pun, dan [abc] dapat cocok dengan a, b, atau c ... Ada info lebih lanjut di situs MSDN .

Steven Murawski
sumber
5

Jika Anda menggunakan SQL Server 2016 atau lebih baru, Anda bisa menggunakannya sp_execute_external_scriptbersama R. Ini memiliki fungsi untuk pencarian Ekspresi Reguler, seperti grepdan grepl.

Berikut ini contoh untuk alamat email. Saya akan meminta beberapa "orang" melalui mesin database SQL Server, meneruskan data untuk orang-orang itu ke R, biarkan R memutuskan orang mana yang memiliki alamat email yang tidak valid, dan meminta R untuk mengembalikan subset orang tersebut ke SQL Server. "Orang-orang" berasal dari [Application].[People]tabel dalam [WideWorldImporters]database sampel. Mereka diteruskan ke mesin R sebagai nama dataframe InputDataSet. R menggunakan fungsi grepl dengan operator "tidak" (tanda seru!) Untuk menemukan orang yang memiliki alamat email yang tidak cocok dengan pola pencarian string RegEx.

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)))

Perhatikan bahwa fitur yang sesuai harus diinstal pada host SQL Server. Untuk SQL Server 2016, itu disebut "SQL Server R Services". Untuk SQL Server 2017, namanya diubah menjadi "SQL Server Machine Learning Services".

Pikiran Penutup Implementasi Microsoft terhadap SQL (T-SQL) tidak memiliki dukungan asli untuk RegEx. Solusi yang diusulkan ini mungkin tidak lebih diinginkan OP daripada penggunaan prosedur tersimpan CLR. Tapi itu memang menawarkan cara tambahan untuk mendekati masalah.

Dave Mason
sumber
4

Jika ada orang lain yang masih melihat pertanyaan ini, http://www.sqlsharp.com/ adalah cara gratis dan mudah untuk menambahkan fungsi CLR ekspresi reguler ke dalam basis data Anda.

John Fisher
sumber
3
Sekali lagi, ini bukan solusi CLR - bukan apa yang diminta OP
Insinyur Terbalik
10
@DaveBoltman: Dia mengajukan pertanyaan pada tahun 2008. Kadang-kadang orang mencari ini dan menemukan pertanyaan ini tanpa ingin menghindari CLR. Ini membantu saya dan mungkin membantu mereka.
John Fisher
Tentu, saya setuju dengan Anda @JohnFisher - ini adalah jawaban yang bermanfaat bagi seseorang yang menggunakan CLR. Tetapi pada tahun 2015, kami masih menginginkan solusi hanya SQL dalam proyek SQL kami (tanpa CLR) karena berbagai alasan, seperti yang dilakukan OP pada tahun 2008. Tahun ini tidak masalah :) Misalnya baterai di mobil Anda dirilis pada 1859 . Tetapi Anda masih ingin menghindari penggunaan baterai yang lebih modern seperti baterai NiMH yang dirilis lebih dari 100 tahun kemudian, karena berbagai alasan (seperti mampu membeli mobil sama sekali :)
Reversed Engineer
2
@DaveBoltman: Anda melewatkan bagian di mana "Orang-orang kadang-kadang mencari ini dan menemukan pertanyaan ini tanpa ingin menghindari CLR". Itu adalah poin kuncinya.
John Fisher
yakin - Anda benar @JohnFisher, Anda memang mengatakan itu. Senang itu membantu Anda, dan saya yakin itu akan membantu orang lain juga
Insinyur Terbalik
2

Anda dapat menggunakan fitur ekspresi reguler VBScript menggunakan OLE Automation. Ini jauh lebih baik daripada overhead untuk membuat dan memelihara perakitan. Pastikan Anda membaca bagian komentar untuk mendapatkan versi modifikasi utama yang lebih baik.

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;

Jika Anda mendapatkan SQL Server blocked access to procedure 'sys.sp_OACreate'...kesalahan, gunakan sp_reconfigureuntuk mengaktifkan Ole Automation Procedures. (Ya, sayangnya itu adalah perubahan level server!)

Informasi lebih lanjut tentang Testmetode ini tersedia di sini

Selamat coding

James Poulose
sumber
sry, saya tahu ini sudah tua, TETAPI: Mengapa VBScript melalui OLE "jauh lebih baik" daripada CLR? Jika Anda HANYA berpikir tentang perawatan, Anda BISA benar, TAPI bagaimana dengan kinerja?
swe
1
@swe By 'way better', saya merujuk pada waktu yang dihemat karena overhead untuk membuat dan memelihara perakitan .NET hanya untuk tujuan ini.
James Poulose