Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Mẫu Regex bên trong chức năng Thay thế SQL?

Bạn có thể sử dụng PATINDEX để tìm chỉ mục đầu tiên của lần xuất hiện của mẫu (chuỗi). Sau đó, sử dụng STUFF để nhồi một chuỗi khác vào mẫu (chuỗi) đã khớp.

Lặp qua từng hàng. Thay thế mỗi ký tự bất hợp pháp bằng những gì bạn muốn. Trong trường hợp của bạn, hãy thay thế không phải số bằng trống. Vòng lặp bên trong là nếu bạn có nhiều hơn một ký tự không hợp lệ trong ô hiện tại của vòng lặp.

DECLARE @counter int

SET @counter = 0

WHILE(@counter < (SELECT MAX(ID_COLUMN) FROM Table))
BEGIN  

    WHILE 1 = 1
    BEGIN
        DECLARE @RetVal varchar(50)

        SET @RetVal =  (SELECT Column = STUFF(Column, PATINDEX('%[^0-9.]%', Column),1, '')
        FROM Table
        WHERE ID_COLUMN = @counter)

        IF(@RetVal IS NOT NULL)       
          UPDATE Table SET
          Column = @RetVal
          WHERE ID_COLUMN = @counter
        ELSE
            break
    END

    SET @counter = @counter + 1
END

Thận trọng:Tuy nhiên, điều này là chậm! Có một cột varchar có thể ảnh hưởng. Vì vậy, việc sử dụng LTRIM RTRIM có thể giúp ích một chút. Bất kể, nó là chậm.

Tín dụng thuộc về câu trả lời StackOverFlow này.

EDITCredit cũng được chuyển đến @srutzky

Chỉnh sửa (bởi @Tmdean) Thay vì thực hiện từng hàng một, câu trả lời này có thể được điều chỉnh cho phù hợp với một giải pháp dựa trên tập hợp hơn. Nó vẫn lặp lại số ký tự không phải số tối đa trong một hàng, vì vậy nó không phải là lý tưởng, nhưng tôi nghĩ nó nên được chấp nhận trong hầu hết các trường hợp.

WHILE 1 = 1 BEGIN
    WITH q AS
        (SELECT ID_Column, PATINDEX('%[^0-9.]%', Column) AS n
        FROM Table)
    UPDATE Table
    SET Column = STUFF(Column, q.n, 1, '')
    FROM q
    WHERE Table.ID_Column = q.ID_Column AND q.n != 0;

    IF @@ROWCOUNT = 0 BREAK;
END;

Bạn cũng có thể cải thiện hiệu quả khá nhiều nếu bạn duy trì một cột bit trong bảng cho biết trường đã được quét chưa. (NULL đại diện cho "Không xác định" trong ví dụ của tôi và phải là cột mặc định.)

DECLARE @done bit = 0;
WHILE @done = 0 BEGIN
    WITH q AS
        (SELECT ID_Column, PATINDEX('%[^0-9.]%', Column) AS n
        FROM Table
        WHERE COALESCE(Scrubbed_Column, 0) = 0)
    UPDATE Table
    SET Column = STUFF(Column, q.n, 1, ''),
        Scrubbed_Column = 0
    FROM q
    WHERE Table.ID_Column = q.ID_Column AND q.n != 0;

    IF @@ROWCOUNT = 0 SET @done = 1;

    -- if Scrubbed_Column is still NULL, then the PATINDEX
    -- must have given 0
    UPDATE table
    SET Scrubbed_Column = CASE
        WHEN Scrubbed_Column IS NULL THEN 1
        ELSE NULLIF(Scrubbed_Column, 0)
    END;
END;

Nếu bạn không muốn thay đổi giản đồ của mình, điều này rất dễ dàng điều chỉnh để lưu trữ các kết quả trung gian trong một biến có giá trị bảng được áp dụng cho bảng thực tế ở cuối.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sự khác biệt giữa CTE và SubQuery?

  2. Sử dụng OBJECT_NAME () để lấy tên đối tượng từ object_id của nó trong SQL Server

  3. Cách thay thế các giá trị Null bằng Không xác định trong Câu lệnh Chọn trong SQL Server - Hướng dẫn SQL Server / TSQL Phần 111

  4. INNER JOIN có thể cung cấp hiệu suất tốt hơn EXISTS không

  5. Làm thế nào để cài đặt localdb riêng biệt?