我有一个名为weather
的varchar列,我想验证它的值。
允许的值来自枚举。与常规枚举列相反 - 每次允许枚举值之一时,此列允许使用逗号分隔的多个枚举成员。
这是我验证简单枚举列的方法:
select *
from TableName
where weather not in ('SUN', 'RAIN', 'SNOW');
weather
包含SUN
或RAIN
或SNOW
。
如果weather
包含SNOW,RAIN
或RAIN,SNOW
怎么办?
我如何验证枚举中只有值?
任何想法?想法?
答案 0 :(得分:0)
Like
运算符很慢,但也许您的数据可以快速运行。试试吧。
select *
from TableName
where (weather not like '%SUN%') and (weather not like '%RAIN%') and (weather not '%SNOW%');
答案 1 :(得分:0)
这种要求不是RDBMS友好的against Codd's 12 Rules !!
但仍有可能。
最简单优雅的解决方案可能是PL/SQL function
。
它使用一个关联数组,将您的枚举值保存为键。
CREATE OR REPLACE FUNCTION WEATHER_LOOKUP(input_string IN VARCHAR2)
RETURN NUMBER
IS
/* Associative array, can be used like a Map */
TYPE weather_tab IS TABLE OF VARCHAR2(20) INDEX BY VARCHAR2(4000);
weathers weather_tab;
temp_weather VARCHAR2(100);
flag NUMBER(1);
BEGIN
/* Create a Map with your enum values as Key */
weathers('SNOW') :=1;
weathers('RAIN') :=2;
weathers('SUN') :=3;
/* If it is comma separated, split the tokens.. and iterate */
FOR I IN 1..REGEXP_COUNT(input_string,',')+1 LOOP
temp_weather := REGEXP_SUBSTR(input_string,'[^,]+',1,I);
IF(weathers.EXISTS(temp_weather)) THEN
flag := 1;
ELSE
flag := 0;
EXIT;
END IF;
END LOOP;
RETURN flag;
END WEATHER_LOOKUP;
/
你的SQL是
SELECT * FROM MY_TABLE
where WEATHER_LOOKUP(weather) = 1;
答案 2 :(得分:0)
允许的值来自枚举。与常规枚举列相反 - 每次允许枚举值之一时,此列允许多个枚举成员,用逗号分隔。
这是不枚举,而是集。一些RDBMS直接支持(like MySQL)。但不是Oracle(AFAIK)。使用Oracle,正确的支持方式是使用嵌套表。
话虽如此,好像我理解得很好,你无法改变你的数据库架构。所以,我会去正则表达式来解决这种情况:
...
where not regexp_like(weather,'^(((SUN)|(RAIN)|(SNOW))[,$])*');
^
从字符串SUN
或RAIN
或SNOW
[,$]
后面是昏迷或字符串结尾但这不会检查重复的值。那是一个要求吗?
答案 3 :(得分:0)
这似乎可以解决问题:
… WHERE NOT REGEXP_LIKE(weather, '^((SUN)|(RAIN)|(SNOW))(,((SUN)|(RAIN)|(SNOW)))*$')
请参阅SQL Fiddle
请:
答案 4 :(得分:0)
您可以使用REGEXP_SUBSTR()
和CONNECT BY
完成此操作(至少在Oracle中 - 我不能代表DB2):
WITH t1 AS (
SELECT 1 AS id, 'SUN,RAIN,SNOW' AS weather
FROM dual
UNION
SELECT 2 AS id, 'SUN,RAIN' AS weather
FROM dual
UNION
SELECT 3 AS id, 'SUN,RAIN,SLEET' AS weather
FROM dual
)
SELECT * FROM (
SELECT DISTINCT id, weather, REGEXP_SUBSTR(weather, '[^,]+', 1, LEVEL) AS weather_part
FROM t1
CONNECT BY REGEXP_SUBSTR(weather, '[^,]+', 1, LEVEL) IS NOT NULL
) WHERE weather_part NOT IN ('SUN','RAIN','SNOW')
有关如何使用CONNECT BY
拆分逗号分隔字符串的更多信息,请参阅StackOverflow上的以下线程:
Splitting string into multiple rows in Oracle