Sql 仅当不同字段中存在具有给定值的多行时,才更新记录集中的列?

Sql 仅当不同字段中存在具有给定值的多行时,才更新记录集中的列?,sql,oracle,Sql,Oracle,我的桌子是这样的: user_id shared_field bool_field ------- ------------ ---------- 1 abc null 2 def null 3 ghi Y 4 ghi null 5 ghi null 6 abc Y 7 j

我的桌子是这样的:

user_id  shared_field  bool_field
-------  ------------  ----------
1        abc           null
2        def           null
3        ghi           Y
4        ghi           null
5        ghi           null
6        abc           Y
7        jkl           null
如果与其他用户(如上面的用户_id 3、4和5)共享同一共享_字段的用户的bool_字段发生更改,则只有一个用户应具有“Y”。其余的在bool_字段列中应该有空值。例如,如果用户_id 4现在应该有“Y”,我必须将用户_id 4的bool_字段更改为“Y”,并确保用户_id 3和5的bool_字段值为null

如果用户不与其他任何人共享共享\u字段值,则该bool\u字段应为空(如上面的用户\u id 1和2中所示)

更新:添加了几行代码,显示多个用户ID可以共享给定的共享字段(例如,1和6都有“abc”;3、4和5都有“ghi”-只有一个“abc”用户应该有一个“Y”,只有一个“ghi”用户应该有一个“Y”等等,而其余的用户在其bool_字段列中都有null;不共享共享_字段值的用户_ID,例如用户_ID 2和7,在其bool_字段列中都应该有null。)清澈如泥,对吗?;)

这句话的作用是:

UPDATE my_table
   SET bool_field = (CASE
                       WHEN user_id = 4 THEN 'Y'
                       ELSE NULL
                      END)
 WHERE shared_field = 'ghi'
   AND (SELECT COUNT(shared_field)
          FROM my_table
         WHERE shared_field = 'ghi') > 1;
问题是:是否有某种方法可以在不事先知道共享_字段值的情况下完成同样的事情?例如(这当然不起作用)更新:“当然”意味着我知道这不起作用,因为它不是正确的Oracle语法!重点是让大家知道我在做什么

UPDATE my_table
   SET bool_field = (CASE
                       WHEN user_id = 4 THEN 'Y'
                       ELSE NULL
                      END)
 WHERE shared_field = (SELECT shared_field FROM my_table WHERE user_id = 4) as sharedVal
   AND (SELECT COUNT(shared_field)
          FROM my_table
         WHERE shared_field = sharedVal) > 1;


更新:这是一条常规SQL语句-我不能使用存储过程。

我已经有一段时间没有在Oracle上工作了,因此请检查以确保此查询返回您要更新的记录列表:

SELECT *
FROM my_table m
WHERE EXISTS (SELECT 1 
        FROM my_table 
        WHERE shared_field = m.shared_field 
        HAVING COUNT(shared_field) > 1);
如果是这样,那么这应该是可行的:

UPDATE my_table
   SET bool_field = (CASE
                       WHEN user_id = 4 THEN 'Y'
                       ELSE NULL
                      END)
WHERE EXISTS (SELECT 1 
        FROM my_table 
        WHERE shared_field = m.shared_field 
        HAVING COUNT(shared_field) > 1);
您也可以尝试此
WHERE
子句:

WHERE shared_field IN (SELECT shared_field 
        FROM my_table 
        GROUP BY shared_field
        HAVING COUNT(shared_field) > 1);

首先,与其说某些东西“不起作用”,不如告诉我们它是如何不起作用的。例如,您发布的查询似乎有语法错误(
as sharedVal
无效,因为您无法为正在
SELECT
列表中计算的表达式指定别名)。但不清楚“不起作用”是否意味着出现语法错误(我们可以相对容易地用错误消息调试),或者它是否意味着查询运行但不执行您想要的操作(如果语法错误得到纠正,我希望查询执行此操作)在这种情况下,了解查询如何不执行您想要的操作会很有帮助

我期待着类似的事情

UPDATE my_table a
   SET bool_field = (CASE WHEN user_id = 4 
                          THEN 'Y' 
                          ELSE NULL 
                      END)
 WHERE shared_field = (SELECT shared_field 
                         FROM my_table b
                        WHERE b.user_id = 4)
   AND EXISTS( SELECT 1
                 FROM my_table c
                WHERE a.shared_field = c.shared_field
                  AND a.user_id     != c.user_id )

假设
user\u id
是主键,则可以使用更新前触发器将相关共享\u字段的所有bool\u字段设置为null,然后让更新过程执行。或者将其放入一个事务过程并调用它,第一步是将它们设置为null,第二步是更新一条记录。如果出现问题,请将其全部回滚。我已经更新了我的帖子,表明我知道第二个示例有语法错误。我用它来说明我想做什么,并认为“当然”会给人们提供线索,因为我知道这一点。您的代码示例看起来应该可以工作。我会在周一试用,并让你知道。是的,这正是我需要的。谢谢!我会在星期一试试,然后告诉你。但是,我没有看到它有任何代码专门指示用户\u id 4的共享\u字段值,而不是给定共享\u字段值的多次出现?是的,这一个给了我所有的用户id记录,这些记录与其他用户id共享一个共享的字段值,而不仅仅是共享用户id 4的共享字段值的用户列表。不过,谢谢你的回复!这可能对其他东西有用。