Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oracle SQL: how to enforce only one value may be 'checked'?

So I have a table in a database which contains the column "SELECTED". The values in this column can only be "CHECKED" or "UNCHECKED". I would like to enforce "CHECKED" can only be used once (like a radiobutton) through a PL/SQL trigger, though I cannot think of how to do this.

First, the idea (in case it didn't become clear):

Initial table "dummy":

ID | SELECTED
--------------
1  | 'UNCHECKED'
2  | 'CHECKED'
3  | 'UNCHECKED'

Then, I execute this query:

UPDATE dummy
SET SELECTED = 'CHECKED'
WHERE ID = 3;

Through a PL/SQL trigger, I'd like to have my table "dummy" to look like this after the execution:

ID | SELECTED
--------------
1  | 'UNCHECKED'
2  | 'UNCHECKED'
3  | 'CHECKED'

I hope you get the idea. I myself have tried to solve this, without success. I came up with the following code:

CREATE OR REPLACE TRIGGER DUMMY_ONE_CHECKED 
AFTER INSERT OR UPDATE ON DUMMY
FOR EACH ROW
DECLARE
  v_checked_is_present DUMMY.SELECTED%TYPE;
BEGIN
  SELECT SELECTED
  INTO v_checked_is_present
  FROM DUMMY
  WHERE SELECTED = 'CHECKED';

  IF v_checked_is_present IS NOT NULL THEN
    UPDATE DUMMY
    SET SELECTED = 'UNCHECKED'
    WHERE SELECTED = 'CHECKED';

    UPDATE DUMMY
    SET SELECTED = 'CHECKED'
    WHERE ID = :NEW.ID;
  END IF;
END;

However, I get the errors ORA-04091, ORA-06512 and ORA-04088 with the following message:

*Cause:    A trigger (or a user defined plsql function that is referenced in
           this statement) attempted to look at (or modify) a table that was
           in the middle of being modified by the statement which fired it.
*Action:   Rewrite the trigger (or function) so it does not read that table.

Clearly, this is not the right solution. I wonder how I could accomplish what I would like to do (if possible at all)?

Thank you in advance!

like image 881
Luc Avatar asked Dec 14 '25 05:12

Luc


1 Answers

I would not design it that way. The database should enforce the rules, not automatically attempt to fix violations of them.

So, I'd enforce that only one row can be CHECKED at a time, like this:

CREATE UNIQUE INDEX dummy_enforce_only_one ON dummy ( NULLIF(selected,'UNCHECKED') );

Then, I'd make it the responsibility of calling code to deselect other rows before selecting a new one (rather than trying to have a trigger do it).

I know that doesn't answer the text of your question, but it does answer the title of your question: "how to enforce only one value..."

like image 144
Matthew McPeak Avatar answered Dec 16 '25 11:12

Matthew McPeak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!