is it possible to create unique constrain in Postgresql, that would take into account column values and work with some value, but not with another?
I have table, where items have "code" that must be unique, but records aren't deleted from table, just marked as deleted (special boolean field "deleted"). I could create unique(code, deleted) to enforce uniqueness, it works if I don't mark 2 rows as deleted with same "code". If I would try to "delete" second row, it will alert that 2 rows will have same unique values and doesn't allow.
What I would like to have, is check unique field "code" for every row, that "deleted" is false.
You can't do this with a consraint. However, in Postgres, a partial unique index would do exactly what you want:
create unique index myindex on mytable(code) where (deleted = false);
You can also phrase this as:
create unique index myindex on mytable(code) where (not deleted);
Related
I'm working on a SQL database, and I have the following table:
Workout Routine
id serial PRIMARY KEY,
user_id integer
REFERENCES users (id)
ON DELETE CASCADE
NOT NULL,
name varchar(255) NOT NULL,
active boolean DEFAULT TRUE,
UNIQUE(user_id, name)
Currently, the combination of user_id, and name are supposed to be unique, meaning that a user cannot have two workout routines with the same name. However, this is not quite what I want.
Instead, I would want the combination user_id and name to be unique only in cases where active = true. In other words, a user should be able to have multiple workouts with the same name that are inactive, but should not be allowed to have duplicates that are active.
Is there a way to enforce this in this table?
A partial index can be used for this:
CREATE UNIQUE INDEX ON table_name (user_id, name) WHERE active;
The fiddle
You can use a partial index to achieve this. The index will only be used for queries that include the active column, and will only be used for queries that include the active column with a value of true. This means that queries that do not include the active column will not use the index, and queries that include the active column with a value of false will not use the index.
CREATE UNIQUE INDEX workout_routine_user_id_name_active
ON workout_routine (user_id, name)
WHERE active = true;
I'm an Oracle guy - but perhaps I can be of help here. Yes, you can model what you want in several ways.
One way is to create two tables, one historical, the other current. The historical would have no unique index other than the PK on the surrogate key ID, whereas the current would also have a unique index on user_id and name.
The second way, using a single table, is to add a nullable date field that represents the closed/inactive date. NULL means active, non-NULL (a date value) would mean inactive. Create a unique index (not a PK) on user_id,name,inactive_date. If SQL Server is like Oracle and allows NULL values in a unique constraint but not multiple NULL values, that will enforce that there can be only one instance of a name for a user_id that is current (having a NULL inactive_date), but allows there to be many inactive rows since they would all have different date values.
If SQL Server acts differently than Oracle then check out the "NULLS NOT DISTINCT" option.
I want to create a table of emails emails where all values in the "email" column must be unique except one for a "redacted#redacted.com" placeholder. Example:
foo#gmail.com
bar#gmail.com
redacted#redacted.com
zoo#gmail.com
redacted#redacted.com
hey#gmail.com
redacted#redacted.com
I see in postgres documentation that it's straightforward to allow null values to be non-duplicative, but is there a way to do this with another value?
You can create a filtered unique index:
create unique index unq_emails_email on (email)
where email <> 'redacted#redacted.com';
I have a table with column position, which has unique and not null constraint.
I have move up/down the selected table item requirement,
for that I am taking the selected index and swapping the indexes.
And saving those two items as in DB.
whenever I am trying to insert first item itself its giving UNIQUE constraint..
Because the item's index is already there in DB.
There is a possibility that I can take temporary index, swapping... and saving .. I think it works.
But is there any other way to achieve this requirement
If you do the update in one Update statement, it'll work fine.
create table t (id number primary key);
insert into t values (1);
insert into t values (2);
commit;
update t set id = case when id = 1 then 2 else 1 end
where id in (1,2);
The easiest way would be to use a temporary value like you say because the constraint will not let you have two rows with the same value at any time.
You can probably derive a temporary value that is in itself unique by basing it on the original value and looking at what kind of data you cannot normally have. For example, negative numbers might work.
Other than that, you could declare the constraint as deferred. Then it won't be enforced until the end of your transaction. But that is probably a bit too much effort/impact.
If the field in question is really only used for sorting (and not for object identity), you could consider dropping the uniqueness altogether. You can use a unique primary key as a tie-breaker if necessary.
I need to add a constraint to a table x which has many to one relation to other table. So the table x has field other_table_id.
There is other column in table x called primary which is boolean type.
I want to make sure that there is none or only one primary=true per one other_table_id.
Multiple rows can have other_table_id equals some same value and primary=false but only one true per other_table_id.
How do I create this constraint?
You need a partial unique index for that:
create unique index idx_unique_other
on table_x (other_table_id)
where primary;
This will only index rows where the value of primary column is true. And for those, the other_table_id has to be unique.
I am trying to add a new unique index on one of my database tables in SQL Server 2008. This is an existing table and the column where I want the unique index already has some duplicate values.
Can I set up a unique index for that column? If so, how?
You can't set this column up with a UNIQUE index if the table already has duplicate values, unless you remove the records containing the duplicate values for that column. This goes to the definition of UNIQUE.
First you are gonna need to delete the duplicate values on your column and then you can create a unique index on it. So lets assume your table has 2 columns, id and column1. To delete duplicate values you need to choose one, it can be random or with some order. So it would be like this:
WITH CTE AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY column1 ORDER BY Id) Corr
FROM YourTable
)
DELETE FROM CTE
WHERE Corr > 1
CREATE UNIQUE INDEX I_Unique ON YourTable(Column1)
No as the name suggest, Unique Index which says key has to be unique. So you cant
See this
If the column already has duplicate values then I would recommend you create a unique composite key instead.
e.g.
So, to handle that issue with this table design, you need to create a unique constraint on the table CustomerID/ProductID columns:
create unique index cust_products_unique on CustomerProducts (CustomerID, ProductID)
So that in essence a combination of fields ensures that the index is unique.
Regards
May not have been true in SQL Server 2008, however you can use Management Studio to do this in later versions such as 2014.
Right click your table
Choose Design
Expand "Identity Specification" and set (is Identity) to Yes
Save