SELECT语句,其中value不是来自枚举

时间:2014-12-28 08:24:37

标签: sql oracle validation enums db2

我有一个名为weather的varchar列,我想验证它的值。

允许的值来自枚举。与常规枚举列相反 - 每次允许枚举值之一时,此列允许使用逗号分隔的多个枚举成员。

这是我验证简单枚举列的方法:

select *
from TableName
where weather not in ('SUN', 'RAIN', 'SNOW');  

weather包含SUNRAINSNOW

如果weather包含SNOW,RAINRAIN,SNOW怎么办? 我如何验证枚举中只有值?

任何想法?想法?

5 个答案:

答案 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))SUNRAINSNOW
    • [,$]后面是昏迷或字符串结尾

但这不会检查重复的值。那是一个要求吗?

答案 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