Mô phỏng hành vi giống như REGEXP trong SQL SQL


7

Tôi đã đăng tương tự trên stackoverflow (xin vui lòng, cho tôi biết nếu tôi phải xóa một cái).

Tôi đang làm việc trên cơ sở dữ liệu DB2 và theo như tôi có thể thấy regrec không được hỗ trợ (không có thư viện bổ sung).

Vì vậy, tôi không thể thực hiện một cái gì đó tương tự như những gì được giải thích trong bài viết này " Mang sức mạnh của biểu thức chính quy phù hợp với SQL "

Bạn có biết nếu tôi có thể "mô phỏng", với một câu lệnh SQL, một biểu thức chính quy như thế này không?

^ a [aofdmep] {1} [az] {1} [a-z0-9] {4} [sidbfkfpo] {1}

Biên tập

Trong giả thuyết trên, chúng tôi thấy rằng nó có thể chấp nhận đối với trường hợp của tôi một ĐÂU Giống như vị ngữ:

WHERE USER_NAME KHÔNG THÍCH 'a_____'

Nhưng nó không an toàn và không bao gồm các trường hợp khác mà tôi không có char cố định mà tôi có thể khớp.


Bạn có thể muốn xem bài viết này: Suy nghĩ về các biểu hiện thông thường
vett Touchyan

1
Vì vậy, điều này thực sự có thể nằm trong lớp câu trả lời, nhưng tôi không chắc: Trong SqlServer, chúng tôi sẽ thực hiện điều này bằng cách sử dụng thành phần regex CLR và công cụ DB2 dường như cho phép sử dụng Java theo cách tương tự. Tại sao bạn không thể đưa nó ra một văn bản Java rất gọn gàng (có thể được sử dụng trong một kịch bản vòng lặp chặt chẽ)
jcolebrand

Câu trả lời:


11

Trước hết, các {1}s là dư thừa, vì vậy nó thực sự chỉ là:

^[aofdmep][a-z][a-z0-9]{4}a[sidbfkfpo]

Đây thực sự là một patterh khá đơn giản ... chỉ cần nhìn vào 8 ký tự đầu tiên của chuỗi là gì và nó luôn là một chuỗi có độ dài cố định, do đó bạn có thể tạo một bảng gồm tất cả các hoán vị, sau đó làm:

WHERE SUBSTR(string_to_match, 1, 8) IN (
  SELECT valid_prefixes FROM table_of_things_to_match
)

Thật không may, đó là 7 * 26 * 36 ^ 4 * 9 ... 2,75 tỷ kết hợp có thể, nhưng, vẫn, các chuỗi cố định, vì vậy bạn có thể làm:

WHERE SUBSTR(string_to_match, 1, 1) IN ('a','o','f','d','m','e','p')
  AND SUBSTR(string_to_match, 2, 1) IN ('a','b','c','d' ... 'z')
  AND SUBSTR(string_to_match, 3, 1) IN ('a','b','c','d' ... 'z','0','1' ... '9')
  AND SUBSTR(string_to_match, 4, 1) IN ('a','b','c','d' ... 'z','0','1' ... '9')
  AND SUBSTR(string_to_match, 5, 1) IN ('a','b','c','d' ... 'z','0','1' ... '9')
  AND SUBSTR(string_to_match, 6, 1) IN ('a','b','c','d' ... 'z','0','1' ... '9')
  AND SUBSTR(string_to_match, 7, 1) = 'a'
  AND SUBSTR(string_to_match, 8, 1) IN ('s','i','d','b','f','k','p','o')

(tất nhiên là điền vào các ...bit)

Rất tiếc, có hai fs trong lớp nhân vật cuối cùng đó, vì vậy chỉ có 2,45 tỷ hoán vị.

Tôi sẽ không giả vờ rằng nó sẽ nhanh ... có thể sẽ không như vậy, nhưng nó sẽ giúp bạn có được mô hình mà bạn đang tìm kiếm. Nếu bạn có xu hướng làm điều này rất nhiều, tôi có thể xây dựng một bảng các ký tự để bạn có một cách dễ dàng để chọn ra alpha / số hoặc alpha-số.


+1. Lựa chọn tốt, cảm ơn rất nhiều! Tôi sẽ chờ một câu trả lời khác nếu có.
tmow

Cuối cùng, sau hơn 2 năm, tôi đã quyết định rằng câu trả lời của bạn là chính xác và rõ ràng nhất. Cám ơn!
tmow

1
Sau khi xem xét điều này hơn 6 năm sau bởi vì nó có một upvote ... làm thế quái nào mà cuối cùng tôi lại di achuyển từ vị trí 1 sang vị trí 7 khi tôi gỡ bỏ {1}s?
Joe

vâng, đúng, nhưng vẫn là câu trả lời đúng.
tmow

11

Vì câu hỏi cũ này đã được đào lên bằng mọi cách, tôi sẽ đề cập rằng bạn có thể sử dụng hỗ trợ XQuery tích hợp trong DB2 để khớp với biểu thức chính quy, một cái gì đó dọc theo dòng

select whatever
from users
where
   xmlcast(
     xmlquery('fn:matches($USER_NAME,"^a[aofdmep][a-z][a-z0-9]{4}[sidbfkfpo]")') 
     as integer) = 1

XMLQUERYở trên gọi matcheshàm XQuery dựa vào cột USER_NAME. Kết quả là một XML boolean, do đó, XMLCASTđược sử dụng để chuyển đổi nó thành một kiểu dữ liệu SQL.


Tôi đang cố gắng đặt một tên cột nơi bạn có $ USER_NAME, nhưng vẫn gặp phải lỗi này . Hãy bình luận.
Lonnie hay nhất

@LonnieBest xin hỏi một câu hỏi riêng. Hãy chắc chắn cung cấp đủ chi tiết, không chỉ là hình ảnh của một thông báo lỗi.
mustaccio


6
SELECT * FROM
   (SELECT 'afr923zs' MyString FROM SYSIBM.SYSDUMMY1)
WHERE substr(MyString,1,1) = 'a' 
AND   substr(MyString,2,1) IN ('a','o','f','d','m','e','p')
AND   substr(MyString,3,1) BETWEEN 'a' AND 'z'
AND  (substr(MyString,4,1) BETWEEN 'a' AND 'z' 
   OR substr(MyString,4,1) BETWEEN '0' AND '9')
AND  (substr(MyString,5,1) BETWEEN 'a' AND 'z' 
   OR substr(MyString,5,1) BETWEEN '0' AND '9')
AND  (substr(MyString,6,1) BETWEEN 'a' AND 'z' 
   OR substr(MyString,6,1) BETWEEN '0' AND '9')
AND  (substr(MyString,7,1) BETWEEN 'a' AND 'z' 
   OR substr(MyString,7,1) BETWEEN '0' AND '9')
AND   substr(MyString,8,1) IN ('s','i','d','b','f','k','p','o');

Cảm ơn nhiều! Rực rỡ như giải pháp Joe nhưng dễ dàng hơn.
vào

Tôi đang kiểm tra xem nó có hoạt động trên DB2 không và làm thế nào để sửa đổi nó cuối cùng
vào

1
Bảng DUAL không tồn tại trong DB2, nhưng có thể sử dụng SYSIBM.SYSDUMMY1.
vào

2

Dựa trên câu trả lời của Leigh Riffel và Joe, bạn có thể cân nhắc sử dụng THÍCH khi bạn có một danh sách dài các ký tự riêng lẻ hoặc khi bạn có nhiều phạm vi ký tự.

SELECT *
  FROM (SELECT 'afr923zs' MyString FROM SYSIBM.SYSDUMMY1) T
 WHERE substr(MyString,1,1) = 'a'
   AND 'aofdmep' like '%'||substr(MyString,2,1)||'%'
   AND substr(MyString,3,1) BETWEEN 'a' AND 'z'
   AND 'abcdefghijklmnopqrstuvwxyz0123456789' like '%'||substr(MyString,4,1)||'%'
   AND 'abcdefghijklmnopqrstuvwxyz0123456789' like '%'||substr(MyString,5,1)||'%'
   AND 'abcdefghijklmnopqrstuvwxyz0123456789' like '%'||substr(MyString,6,1)||'%'
   AND 'abcdefghijklmnopqrstuvwxyz0123456789' like '%'||substr(MyString,7,1)||'%'
   AND 'sidbfkpo' like '%'||substr(MyString,8,1)||'%'
;

Vì bạn sử dụng cùng một danh sách các ký tự nhiều lần, bạn cũng có thể cân nhắc sử dụng cột hằng số CROSS THAM GIA.

SELECT *
  FROM (SELECT 'afr923zs' MyString FROM SYSIBM.SYSDUMMY1) T
  CROSS JOIN (SELECT 'abcdefghijklmnopqrstuvwxyz0123456789' alphanum FROM SYSIBM.SYSDUMMY1) T2
 WHERE substr(MyString,1,1) = 'a'
   AND 'aofdmep' like '%'||substr(MyString,2,1)||'%'
   AND substr(MyString,3,1) BETWEEN 'a' AND 'z'
   AND alphanum like '%'||substr(MyString,4,1)||'%'
   AND alphanum like '%'||substr(MyString,5,1)||'%'
   AND alphanum like '%'||substr(MyString,6,1)||'%'
   AND alphanum like '%'||substr(MyString,7,1)||'%'
   AND 'sidbfkpo' like '%'||substr(MyString,8,1)||'%'
;

Không cần thiết cho ví dụ của bạn, nhưng "bảng" CROSS THAM GIA có thể định nghĩa nhiều cột lớp ký tự được đặt tên.



0

Trong DB2 cho z / OS, SQL sẽ bao gồm PASSING như sau

select whatever
from users
where
   xmlcast(
     xmlquery('fn:matches($USER_NAME,"^a[aofdmep][a-z][a-z0-9]{4}[sidbfkfpo]")'
      PASSING USER as "USER_NAME") 
     as integer) = 1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.