SQL 查询存在且不存在

Posted

技术标签:

【中文标题】SQL 查询存在且不存在【英文标题】:SQL query Exists AND NOT Exists 【发布时间】:2016-03-08 01:15:34 【问题描述】:

我有一个表,我需要从具有 2 个条件的视图中插入数据: 1) 将这些数据插入到 pk 在事务表中不可用但在视图中可用的表中 2) 如果 pk 存在但数据与视图不同,则也插入这些数据

        Insert into table A
    a,
    b,
    c,
    d
SELECT 
a,
b,
c,
d
from View sa
WHERE not Exists 
(Select * FROM table A q
    where SA.a = q.a )
    OR 
    CASE WHEN  Exists
    (Select * FROM table A q
    where SA.a = q.a 
    AND 


                        SA.b <> q.b
                        OR SA.c <> q.c
                        OR SA.d <> q.d
                    ) 

任何帮助表示赞赏!

【问题讨论】:

您尝试的解决方案有什么问题? case 表达式的语法错误。实际上删除 case when 并且它可能有效。 即使在删除大小写后它还是给我语法错误 如何插入已经存在的主键?也许样本数据和预期结果会有所帮助...... netezza 不是 mysql,对吧?我以为是postgres。 【参考方案1】:

我相信这是您的INSERT 与 Netezza 的SELECT 的正确格式。我删除了无效的CASE 表达式,应该没有其他语法错误,但不确定逻辑:

Insert into tableA (a,b,c,d) (
SELECT a,b,c,d
from View sa
WHERE not Exists 
   (Select * FROM tableA q
    where SA.a = q.a 
    )
 OR Exists
    (Select * FROM tableA q2
    where SA.a = q2.a 
    AND SA.b <> q2.b
     OR SA.c <> q2.c
     OR SA.d <> q2.d
    )
)

编辑:我认为它可能一直在抱怨q 表别名的重用。

【讨论】:

ERROR [HY000] ERROR: (2) 不支持这种形式的关联查询 - 考虑重写 这似乎很奇怪,当您离开 OR EXISTS 部分时,SELECT 部分是否在没有插入的情况下运行?如果是这样,也许它不允许重复使用表别名,并且OR EXISTS 需要不是q。只是在黑暗中拍摄,不知道 Netezza。 是的。只有当我运行第二个条件时,才会出现问题 在第二部分尝试使用不同的别名。【参考方案2】:

作为一般规则,相关子查询不适用于 Netezza。显然,您可以在许多情况下使用它们,但通常是以将 MPP 平台转变为串行处理器为代价的。不好。

您可以通过多种方式重写您的插入,但这对我来说似乎是最清楚的。我不知道这个逻辑试图做什么,但我仍然复制了它。如果view 包含重复项,您可能会遇到问题;这可以通过对您的数据多一点了解来解决。

insert into tableA (
  a
  ,b
  ,c
  ,d
)
select
  viw.a
  ,viw.b
  ,viw.c
  ,viw.d
from
  view viw
  join tableA tba on
    (viw.a = tba.a)
    or (
      viw.a = tba.a
      and viw.b <> tba.b
      or viw.c <> tba.c
      or viw.d <> tba.d
    )

您可以通过从实际表中插入tableA 并使用在那里找到的rowids 来消除查看重复的可能性。也许是这样的:

create temporary table temp_view as
  select * from view
distribute on (some_key);

然后收集rowids 像这样插入:

insert into tableA (
  a
  ,b
  ,c
  ,d
)
with mar as ( --Match 'a' records.
  select
    viw.rowid insert_rowid
  from
    temp_view viw
    join tableA tba using (a)
), mnb as ( --Match against 'b'
  select
    viw.rowid
  from
    temp_view viw
    join tableA tba on 
      viw.a = tba.a
      and viw.b <> tba.b
      or viw.c <> tba.c
      or viw.d <> tba.d
), rws as ( --All rowids.
  select * from mar
  union select * from mnb
)
select
  a
  ,b
  ,c
  ,d
from
  temp_view viw
  join rws on rws.insert_rowid = viw.rowid;

【讨论】:

以上是关于SQL 查询存在且不存在的主要内容,如果未能解决你的问题,请参考以下文章

sql 不存在查询

关于如何使用存在和不存在的 PL/SQL 查询的问题

SQL 查询 - 如果存在则更新,否则插入

sql不存在和子查询

SQL查询列不存在错误

SQL 查询 - 不存在 不工作