How force ID generator for class "indentity" to increment for last inserted Id in SQL - sql

I want ask for some advice about,why my <generator class="identity" /> generate id in table not as as last inserted + 1 but like e.g last insert ID is 5, and when save record then a new Id has be for example 7, so ID value 6 is skipped
(i need use identity not increment class due to advantage of this "identity" class for my mySql database)
because in my case i need same ID value for primary key and foreign key, must be equals,,but in this case i got Primary key 7 and Foreign key will generate also but not as incremented by last ID,
both class has Hibernate mappings, with this <generator class="identity" />
What i must use so that to obtain both incremented ID with new record by "identity"?

You have to create your table with a primary key using "AUTO_INCREMENT" such as :
CREATE TABLE person (
id BIGINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
)
Then your GenerationType.IDENTITY must do the job.

Related

Foreign key without correspondence in the referenced table

I'm trying to come up with a solution for an exercise in which I have to create 3 tables: one for employees, one for projects, and one for projects and employees, in which I have to insert the employee's ID and associate with a project ID. In the project_employee table, since it has only 2 columns that reference other tables, I thought I could set them bot as foreign keys, like this:
CREATE TABLE employee_project
(
id_employee numeric FOREIGN KEY REFERENCES employee(id_employee),
id_project numeric FOREIGN KEY REFERENCES project(id_project)
)
Then I stumbled upon a problem: when inserting values on the 3 tables, I noticed that one of the employee's ID number was 4, but on the table employee there was no line with ID 4. Of course, this line wasn't created, but I want to understand: is there a way I could create a line whose ID has no matching record in the referenced table? Could it be a possible mistake in the question, or is there something I'm missing? Thanks in advance for your time!
If there is no rows in employee table with id_employee value 4 then there should not be rows in employee_project table with id_employee value 4. SQL Server will give you an error like below:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__employee__id__75F77EB0". The conflict occurred in database "test", table "dbo.employee", column 'id_employee'.
But if you want to create employee_project with composite primary key on both the column you can try this:
CREATE TABLE employee_project
(
id_employee int not null,
id_project int not null,
primary key(id_employee, id_project )
)

Sqlite - composite PK with two auto-incrementing values [duplicate]

I have a composite primary key {shop_id, product_id} for SQLite
Now, I want an auto-increment value for product_id which resets to 1 if shop id is changed. Basically, I want auto-generated composite key
e.g.
Shop ID Product Id
1 1
1 2
1 3
2 1
2 2
3 1
Can I achieve this with auto-increment? How?
Normal Sqlite tables are B*-trees that use a 64-bit integer as their key. This is called the rowid. When inserting a row, if a value is not explicitly given for this, one is generated. An INTEGER PRIMARY KEY column acts as an alias for this rowid. The AUTOINCREMENT keyword, which can only be used on said INTEGER PRIMARY KEY column, contrary to the name, merely alters how said rowid is calculated - if you leave out a value, one will be created whether that keyword is present or not, because it's really the rowid and must have a number. Details here. (rowid values are generally generated in increasing, but not necessarily sequential, order, and shouldn't be treated like a row number or anything like that, btw).
Any primary key other than a single INTEGER column is treated as a unique index, while the rowid remains the true primary key (Unless it's a WITHOUT ROWID table), and is not autogenerated. So, no, you can't (easily) do what you want.
I would probably work out a database design where you have a table of shops, a table of products, each with their own ids, and a junction table that establishes a many-to-many relation between the two. This keeps the product id the same between stores, which is probably going to be less confusing to people - I wouldn't expect the same item to have a different SKU in two different stores of the same chain, for instance.
Something like:
CREATE TABLE stores(store_id INTEGER PRIMARY KEY
, address TEXT
-- etc
);
CREATE TABLE product(prod_id INTEGER PRIMARY KEY
, name TEXT
-- etc
);
CREATE TABLE inventory(store_id INTEGER REFERENCES stores(store_id)
, prod_id INTEGER REFERENCES product(prod_id)
, PRIMARY KEY(store_id, prod_id)) WITHOUT ROWID;

SQL Primary Key Duplicate Values

I have a table with 2 primary key columns : ID and StudentID.
ID column is set to isIdentity = Yes with auto increment.
I've tested it multiple times before, but for some reason this time, when I insert a duplicate value on StudentID, it does not throw the error but instead added it on to the database. 2 of the same values are displayed when I show the table data.
What can be the problem here?
You have a compound primary key on ID and StudentID. That means you the combination of ID and StudentID together must be unique. Since ID is an identity column that combination of ID and StudentID will always be unique (because ID is already unique on its own).
You can change the primary key to be on ID only. Then you can add a unique index on StudentID. For example:
create unique index idx_studentID on yourTable(StudentID)
That will insure that the StudentID column, in fact, contains only unique values.
It seems like you may not actually need ID column, but that's a little wider discussion than your original question.
You can't have 2 "primary keys". You can have a compound primary key (meaning the combination needs to be unique, which is what it sounds like you have now. Or, You can have one "primary" key and one "unique" constraint which is what it sounds like you want.
You cannot have 2 Primary Keys. You can have multiple Unique Keys if needed, which should help you in your case. Make sure to go back to your table creation and double check which column is your Primary Key and work from there.
Do not mix up identity, primary key and unique key.
Any table can have identity key which you can setup on table. Here seed can be say 1, then increment it by 1. So incremental order will like 1,2,3...and so on.
Primary key, one can define on specific column of the table. Identity key can be used as primary key. But you can have identity column as well primary key on same table. Primary key is one and only for the table.So if you are treating identity as primary key, then you will have no further table column as primary key.
Unique key, can be more than one column with your table.
While fetching rows from table data, if you provide combination of identity key, primary key and unique key then search will be fastest
During my first response, I have mentioned that one can generate identity column by soft coding and it will not be treated as primary key.Following is syntax one can use while creating table.
1] If one wish to set identity column as primary key
--id int identity(1,1) primary key
2] If one doesn't wish to set identity column as primary key and still wish
to us identity column then donot us word primary key for identity column.
--id int identity(1,1)
In this 2] case scenario, one may create primary key on other table column.

many-to-many relationship,, querying one side depending on its elements

Here is the most relevant part of my database schema:
create table TEST (
ID integer not null,
NAME text not null,
constraint PK_TEST primary key (ID),
constraint UNQ_TEST_NAME unique (NAME)
);
create table SESSION (
ID integer not null,
constraint PK_SESSION primary key (ID)
);
create table SESSION_TEST (
SESSION_ID integer not null,
TEST_ID integer not null,
ORDINAL integer not null,
constraint PK_SESSION_TEST primary key (SESSION_ID, TEST_ID),
constraint FK_SESSION_TEST_SESSION_ID foreign key (SESSION_ID) references SESSION (ID) on delete cascade,
constraint FK_SESSION_TEST_TEST_ID foreign key (TEST_ID) references TEST (ID) on delete cascade,
constraint UNQ_SESSION_TEST_SESSION_ID_ORDINAL unique (SESSION_ID, ORDINAL)
);
There are SESSIONS that consist of multiple TESTS. TESTs in SESSIONS have ORDINALs (are ordered). SESSION_TEST is a link table for a many-to-many relationship: one test can be a part of multiple sessions, and one session consists of multiple tests (but one test can be in a session only once, which is the PK).
I am having problems writing an SQL statement that would return true (or 1 actually, as I am using SQLite) for a test with a given ID, if there is a session that has that test and only that test (in other words, the session consists of only one test, the one I am looking for).
For example:
TEST:
ID|NAME
1|aaa
2|bbb
3|ccc
SESSION:
ID
1
2
3
4
SESSION_TEST:
SESSION_ID|TEST_ID|ORDINAL
1|1|1
1|2|2
2|1|1
3|3|1
SESSION with ID = 1 has two TESTs, and SESSIONs 2 and 3 have one test each. I would need to have a select that would return 1/true for inputs 1 and 3, but 0 for 2 (as this TEST is only in SESSION 1, but it's not the only one).
(Sorry about the title, I really didn't know how to put it in a few sentences and make it clear!).
RETURN EXISTS SELECT SESSION_ID FROM
SESSION_TEST
WHERE TEST_ID = #id
AND ORDINAL = 1
AND SESSION_ID NOT IN (SELECT SESSION_ID FROM SESSION_TEST WHERE ORDINAL > 1);
The RETURN EXISTS syntax might be TSQL only, but you get the picture. If the query returns rows, return true, if not return false.

How can an indexed many-to-many set be mapped in NHibernate?

Consider an entity, Entry, that contains a collection of another entity (many-to-many), Category, such that the Entry can be associated with a given Category no more than once (implying a "set" and constrained by the database) and the ordering of the Category entities within the collection is fixed and is defined by an extra field on the mapping table (implying a "list"). What would be the proper mapping for such a case?
Additional details/specifics about the problem this question is trying to address:
Since a <set> doesn't use an <index>, and we can easily maintain uniqueness of the Category entities in the application layer (as opposed to using NHibernate for this), using <list> seems to make sense since it will automatically handle the update of the ordering value in the extra field on the mapping table (which is the biggest "feature" I'd like to use). Unfortunately, when updating the collection, we encounter constraint violations due to the manner in which NHibernate performs the updates (even when the new collection values wouldn't ultimately cause a constraint violation) since we have a unique constraint on the database between the related objects in the mapping table.
More specifically, consider the following database schema:
CREATE TABLE Category (
id int IDENTITY PRIMARY KEY,
name varchar(50)
)
CREATE TABLE Entry (
id int IDENTITY PRIMARY KEY,
data varchar(50)
)
CREATE TABLE EntryCategory (
categoryId int REFERENCES Category (id),
entryId int REFERENCES Entry (id),
index int,
PRIMARY KEY (categoryid, entryId)
)
And the following mappings:
<class name="Category">
<id name="Id">
<generator class="native">
</id>
<property name="name"/>
</class>
<class name="Entry">
<id name="Id">
<generator class="native">
</id>
<property name="data"/>
<list name="Categories" table="EntryCategory">
<key column="entryID"/>
<index column="index"/>
<many-to-many class="Category" column="categoryID"/>
</list>
</class>
Let's consider the initial database state containing the following data:
EntryId CategoryID Index
555 12 0
555 13 1
555 11 2
555 2 3
On load of Entry #555, its Categories list will contain the following elements:
Index Category ID
0 12
1 13
2 11
3 2
If we update this list to remove an element (category 13 at index 1) to look like the following:
Index CategoryID
0 12
1 11
2 2
NHibernate will first delete the entry with highest index value (since the size has reduced), executing the following:
DELETE FROM EntryCategory WHERE entryId = #p0 AND index = #p1;
#p0 = '555', #p1 = '3'
After this update the data in the database looks like this:
EntryId CategoryID Index
555 12 0
555 13 1
555 11 2
Next, it attempts to update the values with the right mappings and starts with this updaet statement:
UPDATE EntryCategory SET CategoryID = #p0 WHERE EntryId = #p1 AND Index = #p2;
#p0 = '11', #p1 = '555', #p2 = '1'
This fails with Violation of PRIMARY KEY constraint since it's attempting to make the data look like this:
EntryId CategoryID Index
555 12 0
555 11 1
555 11 2
It seems that what really needs to happen is that the EntryId and CategoryId are left alone and the Index values are updated instead of leaving the EntryId and Index values alone and updating the CategoryId values. But even in that case, there could be issue if, say, there were also a UNIQUE constraint on EntryID and Index (in addition to the primary key on EntryID and CategoryID).
I think that you'll have to loosen up your constraints to get this to work. Like you said, even if NHibernate updated the index instead of the categoryId, "there could be issue if, say, there were also a UNIQUE constraint on EntryID and Index". This is what I would suggest:
-- Looser constraints. This should work.
CREATE TABLE EntryCategory (
id int IDENTITY PRIMARY KEY,
categoryId int REFERENCES Category (id),
entryId int REFERENCES Entry (id),
index int
);
CREATE INDEX IX_EntryCategory_category ON EntryCategory (entryId, categoryId);
CREATE INDEX IX_EntryCategory_index ON EntryCategory (entryId, index);
I mean, ideally you would have something like the following - but it would be nearly impossible to run any UPDATE queries on it:
-- Nice tight constraints - but they are TOO tight.
CREATE TABLE EntryCategory (
categoryId int REFERENCES Category (id),
entryId int REFERENCES Entry (id),
index int,
PRIMARY KEY (entryId, categoryId),
UNIQUE KEY (entryId, index)
);
Whenever I'm stuck in a situation like this where what I really want is a unique key but for some reason I'm forced to do without it, I settle for an index instead.
In case it's helpful, Ayende has an example with a very similar mapping - a many-to-many list. He doesn't talk about the database schema, though.
Have a look at Oren Eini's blog about the <map> and <set> tags particularly the <map> blog. I think that is what you are after.
<map>
<set>