编写SQL查询时遇到问题
我在写查询时遇到问题。我有一个名为“MYTABLE”的支持表,它有一个名为“TABLENAME”的列,其中可以有一个或多个表名。多个表用逗号分隔 例如:编写SQL查询时遇到问题,sql,oracle,Sql,Oracle,我在写查询时遇到问题。我有一个名为“MYTABLE”的支持表,它有一个名为“TABLENAME”的列,其中可以有一个或多个表名。多个表用逗号分隔 例如: TBLUSER TBLUSER, TBLACCOUNT 我正在尝试编写一个查询,该查询将标识MYTABLE表中任何不是数据库中有效表的条目。我能写下面的 SELECT * FROM MYTABLE T1 LEFT outer JOI
TBLUSER
TBLUSER, TBLACCOUNT
我正在尝试编写一个查询,该查询将标识MYTABLE表中任何不是数据库中有效表的条目。我能写下面的
SELECT *
FROM MYTABLE T1
LEFT outer JOIN ALL_TAB_COLS T2
ON ( upper(T1.TABLENAME) = upper(t2.Table_Name)
AND T2.Owner = 'ME'
)
WHERE TABLE_NAME IS NULL;
它的工作方式正是我想要的——但它只在MYTABLE中的条目包含单个表时工作。当有多个表以逗号分隔时,它将失败。我的SQL技能有些欠缺,我的本能是“为每个人做一个选择”,但我觉得这不是正确的方法(我不知道如何在SQL中做到这一点)。你真的需要重新考虑你的数据库设计。在一个表中的一条记录上保留多个条目,以跟踪这些条目,这是一个巨大的WTF 您需要更改您的设计,这样您就可以使用以下内容,而不是您所描述的内容:
ID TABLENAME
----------------------
1 TBLUSER
2 TBLUSER
2 TBLACCOUNT
其中ID+Tablename是复合主键。这将使您编写的查询能够正常工作(尽管根据我上面提供的简单示例,该查询无法正常工作)
注意我知道这可能不是您在寻找的确切问题,但我觉得说出来很重要,因为未来的用户可能会发现这个问题,并且需要更好地了解数据库规范化实践(由于应用程序的现状,您可能无法做到这一点,因为“情况就是这样”)。你需要重新考虑你的数据库设计。在一个表中的一条记录上保留多个条目,以跟踪这些条目是一个巨大的WTF 您需要更改您的设计,这样您就可以使用以下内容,而不是您所描述的内容:
ID TABLENAME
----------------------
1 TBLUSER
2 TBLUSER
2 TBLACCOUNT
其中ID+Tablename是一个复合主键。这将使您编写的查询能够工作(尽管根据我上面提供的简单示例无法工作)
注意我知道这可能不是您在寻找的确切问题,但我觉得说出来很重要,因为未来的用户可能会发现这个问题,并且需要更好地了解数据库规范化实践(由于应用程序的现状,您可能无法做到这一点,因为”就是这样的”)。您正在MYTABLE.TABLENAME中存储一个字符串,并尝试将其与ALL_TAB_COLS.TABLE_NAME中的一个字符串进行匹配(顺便说一句,我看不出有任何理由在本例中使用ALL_TAB_COLS而不是ALL_TABLE) 如果您的字符串是'TBLUSER,TBLACCOUNT',它将不会等于字符串'TBLUSER'或字符串'TBLACCOUNT'。这就是所有正在测试的表达式
upper(T1.TABLENAME)=upper(t2.Table_Name)
——这两个字符串相等吗?您似乎期望它不知何故“知道”“您的数据恰好是一个以逗号分隔的表名列表
使用字符串比较使您所做的工作正常的暴力方法是将条件更改为,“|124; upper(T1.TABLENAME)| |”,“LIKE”“,”| upper(t2.Table_Name)| |',%
。因此,您基本上要查看TABLE_NAME是否是TABLENAME列值的子字符串
然而,真正的问题是,这不是一个很好的数据库设计。首先,从简单明了的角度来看,为什么要将一列命名为“TABLENAME”(单数),然后在其中放入表示多个表名的值?如果你要这么做,你至少应该把它叫做“TABLENAMELIST”
更重要的是,这通常不是我们在关系数据库中处理事情的方式。如果您的MYTABLE如下所示:
ID TABLENAME
1 TBLUSER
2 TBLUSER, TBLACCOUNT
那么,设计表的更合适的关系方式是:
ID TBL_NUM TABLENAME
1 1 TBLUSER
2 1 TBLUSER
2 2 TBLACCOUNT
然后您的查询将或多或少按原样工作,因为TABLENAME列将始终包含单个表的名称。您正在MYTABLE.TABLENAME中存储一个字符串,并尝试将其与ALL_TAB_COLS.table_name中的一个字符串相匹配(顺便说一句,我看不出在本例中使用ALL_TAB_COLS而不是ALL_表的任何原因) 如果您的字符串是'TBLUSER,TBLACCOUNT',它将不等于字符串'TBLUSER'或字符串'TBLACCOUNT'。这就是表达式
upper(T1.TABLENAME)=upper(t2.Table\u Name)
正在测试的全部内容——这两个字符串相等吗?您似乎期望它以某种方式“知道”您的数据恰好是一个以逗号分隔的表名列表
使用字符串比较使您所做的工作正常的暴力方法是将条件更改为,“|124; upper(T1.TABLENAME)| |”,“LIKE”“,”| upper(t2.Table_Name)| |',%
。因此,您基本上要查看TABLE_NAME是否是TABLENAME列值的子字符串
然而,真正的问题是,这不是一个很好的数据库设计。首先,从简单明了的角度来看,为什么要将一列命名为“TABLENAME”(单数),然后在其中放入表示多个表名的值?如果你要这么做,你至少应该把它叫做“TABLENAMELIST”
更重要的是,这通常不是我们在关系数据库中处理事情的方式。如果您的MYTABLE如下所示:
ID TABLENAME
1 TBLUSER
2 TBLUSER, TBLACCOUNT
那么,设计表的更合适的关系方式是:
ID TBL_NUM TABLENAME
1 1 TBLUSER
2 1 TBLUSER
2 2 TBLACCOUNT
然后您的查询将或多或少按原样工作,因为TABLENAME列始终包含单个表的名称。简短的回答是:
select distinct
atc.table_name
from
mytable mt
,all_tab_cols atc
where atc.owner = 'SOMESCHEMA'
and (
mt.tablename = atc.table_name
or
(
0 < instr(','||replace(upper(mt.tablename),' ','')||','
,','||upper(atc.table_name)||',')
)
)
选择distinct
atc.table_名称
从…起
mytable mt
,所有标签栏atc
其中atc.owner='SOMESCHEMA'
及(
mt.tablename=atc.table\U名称
或
(
0
大卫·科斯塔的帖子已经很好地描述了长答案。短答案是:
select distinct
atc.table_name
from
mytable mt
,all_tab_cols atc
where atc.owner = 'SOMESCHEMA'
and (
mt.tablename = atc.table_name
or
(
0 < instr(','||replace(upper(mt.tablename),' ','')||','
,','||upper(atc.table_name)||',')
)
)
选择distinct
atc.table_名称