Check constraint for a flag column - sql

Database is MS SQLServer
Data example:
| Name | defaultValue | value |
| one | true | valone |
| one | false | valtwo |
| one | false | valthree |
I'm after a way of constraining the table such that each 'Name' can only have one row with 'defaultValue' set to true

Create a computed column like this:
ALTER TABLE yourtable
ADD ValueCheck AS CASE defaultValue
WHEN true THEN 1
WHEN false THEN NULL
END
and then add unique constraint for (Name, ValueCheck)

I liked Michael's idea but it will only allow you one false value per name in SQL Server. To avoid this how about using
ALTER TABLE yourtable
ADD [ValueCheck] AS
(case [defaultValue] when (1) then ('~Default#?#') /*Magic string!*/
else value end) persisted
and then add unique constraint for (Name, ValueCheck).
I am assuming that name, value combinations will be unique. If the value column does not allow NULLs then using NULL rather than the magic string would be preferable otherwise choose a string that cannot appear in the data (e.g. 101 characters long if the value column only allows 100 chars)

You can use a TRIGGER to validate this constraint on update or insert events and roll back the transaction if it was invalid.

Related

In Postgres, can you update CITEXT value to a different casing?

Running a posgresql database.
I have a table with CITEXT columns for case-insensitivity. When I try to update a a CITEXT value to the same word in different casing it does not work. Postgres returns 1 row updated, as it targeted 1 row, but the value is not changed.
Eg
Table Schema - users
Column | Type
___________________________
user_id | PRIMARY KEY SERIAL
user_name | CITEXT
age | INT
example row:
user_id | user_name | age
_________________________________
1 | ayanaMi | 99
SQL command:
UPDATE users SET user_name = 'Ayanami' WHERE user_id = 1
The above command turns 1 UPDATED, but the casing does not change. I assume this is because postgres sees them as the same value.
The docs state:
If you'd like to match case-sensitively, you can cast the operator's arguments to text.
https://www.postgresql.org/docs/9.1/citext.html
I can force a case sensitive search by using CAST as such:
SELECT * FROM users WHERE CAST(user_name AS TEXT) = `Ayanami`
[returns empty row]
Is there a way to force case sensitive updating?

How can I update the table in SQL?

I've created a table called Youtuber, the code is below:
create table Channel (
codChannel int primary key,
name varchar(50) not null,
age float not null,
subscribers int not null,
views int not null
)
In this table, there are 2 channels:
|codChannel | name | age | subscribers | views |
| 1 | PewDiePie | 28 | 58506205 | 16654168214 |
| 2 | Grandtour Games | 15 | 429 | 29463 |
So, I want to edit the age of "Grandtour Games" to "18". How can I do that with update?
Is my code right?
update age from Grandtour Games where age='18'
No, in update, you'll have to follow this sequence:
update tableName set columnWanted = 'newValue' where columnName = 'elementName'
In your code, put this:
update Channel set age=18 where name='Grandtour Games'
Comments below:
/* Channel is the name of the table you'll update
set is to assign a new value to the age, in your case
where name='Grandtour Games' is referencing that the name of the Channel you want to update, is Grandtour Games */
alter table changes the the schema (adding, updating, or removing columns or keys, that kind of thing).
Update table changes the data in the table without changing the schema.
So the two are really quite different.
Here is your answer -
-> ALTER is a DDL (Data Definition Language) statement
UPDATE is a DML (Data Manipulation Language) statement.
->ALTER is used to update the structure of the table (add/remove field/index etc).
Whereas UPDATE is used to update data.
Hope this helps!

SQLITE: Transaction to check constraints after commit

I'm currently working on an sqlite table where I have to do the following:
ID | Name | SortHint
---|-------|---------
0 | A | 1
1 | B | 2
2 | C | 3
ID is the primary key and SortHint is a column with the UNIQUE-constaint. What I have to do is to modify the table, for example:
ID | Name | SortHint
---|-------|---------
0 | A | 3
1 | B | 1
2 | C | 2
The Problem: Because of the UNIQUE I can't simply update one row after another. I tried:
BEGIN TRANSACTION;
UPDATE MyTable SET SortHint = 3 WHERE ID= 0;
...
COMMIT;
But the first update query immideatly fails with:
UNIQUE constraint failed: MyTable.SortHint Unable to fetch row
So, is there a way to "disable" the unique constaint for a transaction and only check all of them once the transaction is committed?
Notes:
I can't modify the table
It works if I only use SortHint values that are not already in the table
I know how to "workaround" this problem, but I would like to know if there is a way to do this as described above
One possibility is to drop the unique constraint and then add it again. That is a little bit expensive, though.
Another would be to set the values to negative values:
UPDATE MyTable
SET SortHInt = - SortHint;
UPDATE MyTable
SET SortHint = 3
WHERE ID = 0;
. . .
If you cannot modify the table, you are not able to remove the constraint.
A workaround could be to change the SortHint to a range that is not in use.
For example you could add 10,000 to all of them. Commit.
Then change to the right number at once which have become free now.
Maybe test afterwards that no numbers of 10,000 or higher exist anymore.

What is the best way to change the type of a column in a SQL Server database, if there is data in said column?

If I have the following table:
| name | value |
------------------
| A | 1 |
| B | NULL |
Where at the moment name is of type varchar(10) and value is of type bit.
I want to change this table so that value is actually a nvarchar(3) however, and I don't want to lose any of the information during the change. So in the end I want to end up with a table that looks like this:
| name | value |
------------------
| A | Yes |
| B | No |
What is the best way to convert this column from one type to another, and also convert all of the data in it according to a pre-determined translation?
NOTE: I am aware that if I was converting, say, a varchar(50) to varchar(200), or an int to a bigint, then I can just alter the table. But I require a similar procedure for a bit to a nvarchar, which will not work in this manner.
The best option is to ALTER bit to varchar and then run an update to change 1 to 'Yes' and 0 or NULL to 'No'
This way you don't have to create a new column and then rename it later.
Alex K's comment to my question was the best.
Simplest and safest; Add a new column, update with transform, drop existing column, rename new column
Transforming each item with a simple:
UPDATE Table
SET temp_col = CASE
WHEN value=1
THEN 'yes'
ELSE 'no'
END
You should be able to change the data type from a bit to an nvarchar(3) without issue. The values will just turn from a bit 1 to a string "1". After that you can run some SQL to update the "1" to "Yes" and "0" to "No".
I don't have SQL Server 2008 locally, but did try on 2012. Create a small table and test before trying and create a backup of your data to be safe.

MySQL: Multiple Inserts for a single column

I'm looking for a way to do multiple row inserts when I'm only inserting data for a single column.
Here is the example table:
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | tinyint(4) | NO | PRI | NULL | auto_increment |
| name | varchar(40) | NO | UNI | NULL | |
+-------+-------------+------+-----+---------+----------------+
I want to be able to insert something like ('admin', 'author', 'mod', 'user', 'guest') into the name column for each row.
The MySQL documentation shows that multiple inserts should be in the format:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
However my statement ends up looking like this:
INSERT INTO User_Role(name) VALUES ('admin','author','mod','user','guest');
And I get the following:
ERROR 1136 (21S01): Column count doesn't match value count at row 1
Meaning that it thinks I'm trying to do a single row insert.
I'm not sure if I'm just missing something simple here, but I don't see anything in particular in the MySQL docs for this use case.
your syntax is a bit off. put parentheses around each data "set" (meaning a single value in this case) that you are trying to insert.
INSERT INTO User_Roll(name) VALUES ('admin'), ('author'), ('mod'), ('user'), ('guest');
I will advise you Don't put multiple values in a column.
make a new table:
INSERT INTO table_name (id, name) VALUES (1, 'name1'), (1, 'name2'), (1, 'name3'), (1, 'name4');