Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL constraint to prevent updating a column based on its prior value

Can a Check Constraint (or some other technique) be used to prevent a value from being set that contradicts its prior value when its record is updated.

One example would be a NULL timestamp indicating something happened, like "file_exported". Once a file has been exported and has a non-NULL value, it should never be set to NULL again.

Another example would be a hit counter, where an integer is only permitted to increase, but can never decrease.

If it helps I'm using postgresql, but I'd like to see solutions that fit any SQL implementation

like image 250
andyortlieb Avatar asked Jan 16 '13 20:01

andyortlieb


People also ask

How do I restrict a column value in SQL?

The CHECK constraint is used to limit the value range that can be placed in a column. If you define a CHECK constraint on a column it will allow only certain values for this column. If you define a CHECK constraint on a table it can limit the values in certain columns based on values in other columns in the row.

Which SQL constraint do we use to set some value to a field whose value has not been added explicitly?

Which SQL constraint do we use to set some value to a field whose value has not been added explicitly? Explanation: The DEFAULT constraint is used to set a default value for a column which comes into use when a value for a field in that column is not set.

Which of the following constraint prevents their value being altered?

UNIQUE constraint ensures that all the values stored in a column are different from each other. The UNIQUE Constraint prevents two records from having identical values in a column, i.e., the values must not be repeated. We can use UNIQUE constraint in a single column or multiple columns.

What is the purpose of a check constraint?

A check constraint is a rule that specifies the values that are allowed in one or more columns of every row of a base table. For example, you can define a check constraint to ensure that all values in a column that contains ages are positive numbers.


2 Answers

Use a trigger. This is a perfect job for a simple PL/PgSQL ON UPDATE ... FOR EACH ROW trigger, which can see both the NEW and OLD values.

See trigger procedures.

like image 98
Craig Ringer Avatar answered Oct 02 '22 22:10

Craig Ringer


lfLoop has the best approach to the question. But to continue Craig Ringer's approach using triggers, here is an example. Essentially, you are setting the value of the column back to the original (old) value before you update.

CREATE OR REPLACE FUNCTION example_trigger()
  RETURNS trigger AS
$BODY$
BEGIN
     new.valuenottochange := old.valuenottochange;
     new.valuenottochange2 := old.valuenottochange2;
     RETURN new;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;



DROP TRIGGER IF EXISTS trigger_name ON tablename;
  CREATE TRIGGER trigger_name BEFORE UPDATE ON tablename
    FOR EACH ROW EXECUTE PROCEDURE example_trigger();
like image 25
Tom Gerken Avatar answered Oct 03 '22 00:10

Tom Gerken