簡體   English   中英

MySQL 選擇包含前導或尾隨空格的字段

[英]MySQL select fields containing leading or trailing whitespace

我可以使用 MySQL TRIM()方法使用UPDATE清除包含前導或尾隨空格的字段,如下所示:

UPDATE Foo SET field = TRIM(field);

我想在運行之前實際查看這將影響的字段。 我試過了,但返回 0 結果:

SELECT * FROM Foo WHERE field != TRIM(field);

看起來這應該有效,但事實並非如此。

有人有解決方案嗎? 另外,好奇為什么這不起作用......

CHARVARCHAR類型中所述

所有 MySQL 歸類都是PADSPACE類型。 這意味着 MySQL 中的所有CHARVARCHAR值都會在不考慮任何尾隨空格的情況下進行比較。

LIKE運算符的定義中,手冊指出:

特別是,尾隨空格很重要,這對於使用=運算符執行的CHARVARCHAR比較而言並非如此:

正如這個答案中提到的:

此行為在 SQL-92 和 SQL:2008 中指定。 出於比較的目的,較短的字符串被填充到較長字符串的長度。

從草案(8.2 <比較謂詞>):

如果 X 的字符長度不等於 Y 的字符長度,那么為了比較的目的,較短的字符串被有效地替換為自身的副本,該副本已通過連接擴展到較長字符串的長度在一個或多個填充字符的右側,其中填充字符是根據 CS 選擇的。 如果 CS 具有 NO PAD 特性,則該填充字符是一個與實現相關的字符,不同於 X 和 Y 字符集中的任何字符,其排序規則少於 CS 下的任何字符串。 否則,填充字符是 <space>。

一種解決方案:

SELECT * FROM Foo WHERE CHAR_LENGTH(field) != CHAR_LENGTH(TRIM(field))
SELECT *
FROM 
    `foo`
WHERE 
   (name LIKE ' %')
OR 
   (name LIKE '% ')

這是一個使用RegEx的示例

SELECT *
FROM 
    `foo`
WHERE 
   (name REGEXP '(^[[:space:]]|[[:space:]]$)')

另一種解決方案可能是使用SUBSTRING()IN將字符串的最后一個和第一個字符與空白字符列表進行比較...

(SUBSTRING(@s,  1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s, -1, 1) IN (' ', '\t', '\n', '\r'))

...其中@s是任何輸入字符串。 根據您的情況,將額外的空白字符添加到比較列表中。

這是一個簡單的測試,用於演示該表達式如何處理各種字符串輸入:

SET @s_normal = 'x';
SET @s_ws_leading = '\tx';
SET @s_ws_trailing = 'x ';
SET @s_ws_both = '\rx ';

SELECT
    NOT(SUBSTRING(@s_normal,      1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s_normal,     -1, 1) IN (' ', '\t', '\n', '\r')) test_normal      #=> 1 (PASS)
  ,    (SUBSTRING(@s_ws_leading,  1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s_ws_leading, -1, 1) IN (' ', '\t', '\n', '\r')) test_ws_leading  #=> 1 (PASS)
  ,    (SUBSTRING(@s_ws_trailing, 1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s_ws_trailing,-1, 1) IN (' ', '\t', '\n', '\r')) test_ws_trailing #=> 1 (PASS)
  ,    (SUBSTRING(@s_ws_both,     1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s_ws_both,    -1, 1) IN (' ', '\t', '\n', '\r')) test_ws_both     #=> 1 (PASS)
;

如果這是你要做的事情,你也可以為它創建一個函數:

DROP FUNCTION IF EXISTS has_leading_or_trailing_whitespace;

CREATE FUNCTION has_leading_or_trailing_whitespace(s VARCHAR(2000))
  RETURNS BOOLEAN
  DETERMINISTIC
RETURN (SUBSTRING(s, 1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(s, -1, 1) IN (' ', '\t', '\n', '\r'))
;

# test
SELECT
    NOT(has_leading_or_trailing_whitespace(@s_normal     )) #=> 1 (PASS)
  ,     has_leading_or_trailing_whitespace(@s_ws_leading )  #=> 1 (PASS)
  ,     has_leading_or_trailing_whitespace(@s_ws_trailing)  #=> 1 (PASS)
  ,     has_leading_or_trailing_whitespace(@s_ws_both    )  #=> 1 (PASS)
;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM