SQLite UNIQUE constraint dependent on another column - sql

I have a Java file that creates a subjects table in SQLite like so:
public static final String CREATE_SUBJECTS_TABLE = "create table " + SUBJECTS_TABLE_NAME +" (ID INTEGER PRIMARY KEY AUTOINCREMENT,SUBJECT TEXT,LEVEL INTEGER)";
db.execSQL(CREATE_SUBJECTS_TABLE);
If I wanted to make SUBJECT TEXT unique I could edit it to say SUBJECT TEXT UNIQUE, however this would mean I couldn't have the same subject at multiple levels. I want a way to be able to have the same subject at multiple levels, but not have a repeat of a subject with the same level. A UNIQUE constraint, but only within subjects with the same value in the level column.
I was wondering if there is a built in way to do this, or if I'll have to code it myself. If so, is there a common syntax that I should be using to achieve this?
Thanks

Sounds like you actually want the (subject, level) pair to be unique. That would let you have duplicate subjects as long as the levels were different but duplicate subjects with the same level would not be allowed. A standard unique constraint supports this so you could add unique(subject, level) at the end of your table's definition:
public static final String CREATE_SUBJECTS_TABLE = "create table " + SUBJECTS_TABLE_NAME + " (..., unique(subject, level))";

Related

Insert query if no duplicate of singular value

I have a table with various planets on it and users have the option to create their own planets. However, I do not want there to be planets with the same name so I am attempting to create a query that only inserts a planet if it's name is not the duplicate of an already created planet. This is what I have so far for my query:
private static final String INSERT_QUERY = "INSERT INTO tutorial.planet"
+ " (planet_name, planet_type, habitable_flg, planet_radius, distance_from_sun, days_in_year, population)"
+ " VALUES"
+ " (:name, :type, :habitable, :radius, :distance, :days, :population)"
+ " WHERE NOT EXISTS (SELECT planet_name FROM tutorial.planet WHERE tutorial.planet.name = :name)";
The "WHERE NOT EXISTS" line is in question as my query works for regular insertions whenever I exclude that line.
Why don't you use a unique constraint on the planet_name column?
A UNIQUE constraint will by default restrict the addition of a new record in the database. The database will generate an error (like this: Violation of UNIQUE KEY constraint) when trying to add a new record with the same planet_name
When this is handled by the database you will have to catch the exception thrown in your code.
This constraint can be added like this:
ALTER TABLE tutorial.planet
ADD CONSTRAINT Unique_Planet_Name UNIQUE (planet_name);
See https://learn.microsoft.com/en-us/sql/relational-databases/tables/create-unique-constraints?view=sql-server-ver15

How to create a primary key column and fill it with integer values on HANA SQL

I searched but only could found partial answer to this question
The goal would be here to create a new ID column on an existing table.
This new column would be the primary key for the table and I simply want it to be filled with integer values from 1 to number of rows.
What would be the query for that?
I know I have to first alter table to create the new column :
ALTER TABLE <MYTABLE> ADD (ID INTEGER);
Then I could use the series generator :
INSERT INTO <MYTABLE.ID> SELECT SERIES_GENERATE_INTEGER(1,1,(number of rows));
Once the column is filled I could use this line:
ALTER TABLE <MYTABLE> ADD PRIMARY KEY ("ID");
I am sure there is an easier way to do this
You wrote that you want to add a "new ID column to an existing table" and fill it with unique values.
That's not a "standard" operation in any DBMS, as the usual assumption is that records are created with a primary key and not retro fitted.
Thus, "ease" of operation for this is relative to what else you want to do.
For example, if you want to continue using this ID as a primary key for further operations, then using a once-off generator function like the SERIES_GENERATE_INTEGER or a query won't be very helpful since you have to avoid duplicates of already existing values.
Two, relatively easy, options come to mind:
Using a sequence:
create sequence myid;
update <table> set ID = myid.nextval;
And for succeeding inserts:
insert into <table> (id, ..., ...) VALUES (myid.nextval, ..., ...) ;
Note that this generates a value for every existing record and not a predefined set of size X.
Using a GUID
By using a GUID you generate a unique value every time you call the 'SYSUUID' function in SAP HANA. check docu here
Something like
update <table> set ID = SYSUUID;
should do the trick here.
Subsequent inserts would simply call the function for values of ID.

Specify the format of a string with letters and numbers in triggers SQL

I am actually writing a trigger with Oracle and I want to specify the format of a variable but I'm not finding the proper syntax to do that.
I have a table 'Person' which gathers students and professors and all of them have a matricule. Professors have a "pmatricule" which means a string with "p" followed by a chain of 3 to 6 numbers. Example : p456123
Students have only a matricule with 3 to 7 numbers such as : 1234567
My triggers has to compare the new matricule I want to input in my table 'Person' to check if it respects the format I described.
Has someone the syntax to do such a thing ? I have searched for a long time but my trigger is not working whatever I try.
You can do this with a table level CHECK constraint. You haven't provided a table description so column names are guesses.
alter table person add constraint person_matricule_ck check
( ( person_type = 'PROFESSOR' and regexp_like(matricule, '^p[0-9]{6}$') )
or ( person_type = 'STUDENT' and regexp_like(matricule, '^[0-9]{7}$') )
)
/
We shouldn't use triggers for rules which can be enforced with constraints: constraints are both idiomatic SQL and more efficient.

How can I create a table that only allows data to insert if they are allowed

How can i create a table, that allows only to put data in NAME, if the data matches with the data that i want to be allowed in NAME. So like Bla1 or Bla2.
CREATE TABLE Table1 (
NAME VARCHAR(23)
NAME has to be one of them: ('Bla1', 'Bla2')
)
The best way to do it is probably to have a second table with all the allowed names in it, and making a FOREIGN KEY from the name field in your Table1 to the name field in that other table. That'll automatically fail any insert queries for which the name is not contained in the list of allowed names.
This has an advantage over things like ENUM and such in that it does not require you to rebuild your table (which is a very expensive operation) every time you want to allow another name and it also allows you to later add additional related info to each name by adding it to the other table.
Here's a great article on why using a foreign key is much better than using enums or other such checks in the table itself: http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/
Try this:
CREATE TABLE Table1 (
name VARCHAR(23) CHECK( name IN ('Bla1','Bla2') )
);

How to set primary key on a field in fusion table

I have a table named "Testing". fields in this table are Id,Name and Description.
I want to make Id field as a primary key i.e. only unique values should be entered in this field.
Thanks,
Himanshu
When you do CREATE TABLE
In addition to the column names you specify in the CREATE TABLE statement, Google Fusion Tables will create a column named ROWID that contains an automatically-assigned, unique ID number for each row.
I don't think you can do this. It appears to be a much requested feature: https://code.google.com/p/fusion-tables/issues/detail?id=112
It's not available. I use a workaround that performs a COUNT(ROWID) query for the unqiue ID I'm about to insert and then take steps depending on whether or not that unique ID is already in the table.
The basic algo is something like this (using Google Apps Script):
var check = FusionTables.Query.sql("SELECT COUNT(ROWID) FROM <table ID> WHERE 'Trip ID' = '" + rowID + "'");
if (check.rows[0][0] > 0) {
// ID already exists
} else {
// ID is new, insert the record.
}