[英]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);
看起來這應該有效,但事實並非如此。
有人有解決方案嗎? 另外,好奇為什么這不起作用......
所有 MySQL 歸類都是
PADSPACE
類型。 這意味着 MySQL 中的所有CHAR
和VARCHAR
值都會在不考慮任何尾隨空格的情況下進行比較。
在LIKE
運算符的定義中,手冊指出:
正如這個答案中提到的:
此行為在 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.