I have a question regarding the primary key or composite key.
Database: SQL Server
The following occurs, I have to import data from another system.
One of the tables has a triple key (company, code and year). I'll call it Sale.
And there is, for example, a table that has a quadruple key (company, code, year and item) that I will call SaleItem.
I will have to import this information but I thought about not creating a triple, quadruple key in my bank, but creating a uniqueidentifier (primary) key from the key, but I have to store this information separately.
Sale:
SaleId Uniqueidentifier (Company: 1 byte, Code: 8 bytes, Year: 2 bytes, 5 bytes 0) PK
Company byte
Code bigint
Year byte
...
In the SaleItem table I thought of also creating a primary key
SaleItemId Uniqueidentifier(Company: 1 byte, Code: 8 bytes, Year: 2 bytes, Item: 2 bytes, 3 bytes 0) PK
SaleId Uniqueidentifier (Company: 1 byte, Code: 8 bytes, Year: 2 bytes, 5 bytes 0) FK
Item tinyint
...
Or in that same table make a composite key of SaleId and Item
SaleId Uniqueidentifier (Company: 1 byte, Code: 8 bytes, Year: 2 bytes, 5 bytes 0) PK FK
Item tinyint PK
...
There will also be tables referencing SaleItem.
What would be better all composed? All primary key? Or?
Related
I am trying to create a many-to-many relationship between two tables Asset and Inventory, I created an intermediate table called Asset_Inventory
One or more assets can be in an inventory, and an inventory can be in one or more assets,but it does not allow me to insert data
Mistake
The data in row 2 was not committed. Error source Message: Violation of PRIMARY KEY CONSTRAINT
PK_INVENTORY_ASSET. Cannot insert duplicate key in object dbo.Inventory_Asset. The duplicate key value (1,1).
-- TABLE INVENTORY
GO
CREATE TABLE Inventory
(
[inventory_id] INT NOT NULL IDENTITY(1,1),
[company_id] INT,
[name] VARCHAR(50),
[observations] VARCHAR(500),
[date_created] DATETIME DEFAULT(GETDATE()),
CONSTRAINT PK_INVENTORY PRIMARY KEY (inventory_id),
CONSTRAINT FK_INVENTORY_COMPANY FOREIGN KEY(company_id) REFERENCES Company(company_id)
)
-- TABLE ASSET
GO
CREATE TABLE Asset
(
[asset_id] INT NOT NULL IDENTITY(1,1),
[company_id] INT,
[code] INT,
[model_name] VARCHAR(50),
[model_number] VARCHAR(50),
[serial_number] VARCHAR(30),
[price] DECIMAL(10,2),
CONSTRAINT PK_ASSET_ID PRIMARY KEY(asset_id),
CONSTRAINT FK_ASSET_COMPANY FOREIGN KEY(company_id) REFERENCES Company(company_id),
CONSTRAINT UQ_ASSET_CODE UNIQUE(code)
)
--TABLE INVENTORY_ASSET
CREATE TABLE Inventory_Asset
(
asset_id INT,
inventory_id INT,
CONSTRAINT PK_INVENTORY_ASSET PRIMARY KEY (asset_id,inventory_id),
CONSTRAINT FK_ASSET_ID FOREIGN KEY (asset_id) REFERENCES Asset(asset_id),
CONSTRAINT FK_IVENTORY_ID FOREIGN KEY (inventory_id) REFERENCES Inventory(inventory_id)
)
UPDATED
it's hard for me to ask this question
N companies have many assets; you need to have control over them. Have a list of assets by company, to which employee it was assigned, or in which department of the company that asset is located. a total of assets by company etc..
What is the purpose of this?
I need to physically label (bar code) each asset with a unique code
Cell phones, monitors, keyboards, servers, PCs, laptops, chairs, furniture, etc...
Once all the assets have been tagged in the
company 1
company 2
company 3
I have to scan each code printed on the asset and make a monthly cut
I have to create a report with this information
In the company 1 an inventory was made in the month of January
Cut of the month of January:
20 monitors (10 dell , 10hp)
20 chairs
10 computers
the next month this cut is made again to see if there is the same quantity, if the 2 inventories of the month of January and February are not the same, some asset was stolen and to be able to identify this
an inventory can have one or more assets, and an asset can be in one or more inventories.
I think I can do this with the Inventory_Asset table
asset_id
iventory_id
1
1
1
1
2
1
3
1
1
1
1
2
2
2
1
2
6
2
1
3
4
3
3
3
1
3
Am I wrong with my solution?
--TABLE INVENTORY_ASSET
CREATE TABLE Inventory_Asset
(
[inventory_id] INT,
[asset_id] INT,
CONSTRAINT FK_ASSET_ID FOREIGN KEY (asset_id) REFERENCES Asset(asset_id),
CONSTRAINT FK_IVENTORY_ID FOREIGN KEY (inventory_id) REFERENCES Inventory(inventory_id)
)
CONSTRAINT PK_INVENTORY_ASSET PRIMARY KEY (asset_id,inventory_id),
PRIMARY KEYS must be unique. That is why you can't add this -- since it conflicts with your primary key. If you don't want that to be unique but you do expect to use it as an index you can make an index that does not enforce uniqueness and make something else your primary key.
The answers and comments here are all correct; but perhaps we need to review what a many-to-many relation can be used for.
Option 1: we just need a link between two entities
This is what you have done. Basically it will serve if you want to know in which Inventories a given Asset is, which Assets a given Inventory holds, etc. In this scenario when you have established the link once (Asset 1 is in Inventory 1) there's no reason to re-establish it with further records.
Option 2: we want to store some information about the relation
This is what I suspect you really wanted. Suppose for instance you want to store how many Assets of type 1 are in Inventory 1. In this case what you want is to add a "Quantity" column to your Inventory_asset table. Once more, if there are 3 Assets of type 1 in Inventory 1 you won't duplicate the records: you will just create one record and put 3 in the new column.
Option 3: we really need multiple records
Suppose you want to store not only how many Assets of a given type are in a given Inventory, but also on which date a few of them were put there. So you may have 2 type 1 Assets put in Inventory 1 on May, 1st, and other 3 of them on May, 15th. In this case the date must become part of the PK, so that the system (and you too!) can distinguish between the different records. You may also decide to create an auto-increment column and use it as a PK instead; but note that while it may be simpler to handle, it would allow for unvoluntarily creating duplicate records, so I wouldn't recommend it.
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;
I have this scenario in a POC of Cassandra.
A table
CREATE TABLE B (B-UID UUID,
A-UID UUID,
CREATED_AT timestamp ,
JSON text,
PARENT_B-UID UUID,
POSTALCODE text,
CUSTOMER_TYPE text,
START_DATE timestamp,
END_DATE timestamp,
SOME_PRICE int,
PRIMARY KEY (B-UID));
24 k rpm of write / 2 k rpm of read. For 1 A-UID I'll have 67 B-IUD in most cases.
In the life cycle of my app I'll have to Search all the B-IUD for a specific A-IUD.
My question is: Is it better create the table with a composite primary key or create an index to A-IUD? The writing performance will be affected with a composite primary key?
I already read the docs at DataStax and the example they have written there is not too good for my case, at least in my understanding!!! :)
Try avoiding secondary indexes to the maximum extent
If the only query is to retrieve all B-IUD for a particular A-IUD, have a composite primary key (A-IUD, B-IUD).
If you also need to search for a particular B-IUD, have two tables
1 : Table 1 : with B-IUD as the primary key and remaining columns as is
2 : Table 2 : with a composite primary key (A-IUD, B-IUD) and remaining columns as is
Is there any difference between INT PRIMARY KEY and INTEGER PRIMARY KEY when defining a schema for a table?
When int primary key is used, I got sqlite_autoindex thing generated;
when integer primary key , I got sqlite_sequence table generated.
what's the difference? what side effects can have the first and second variants?
UPDATE: SQLite's ROWID column is now a 64-bit integer:
In SQLite, a column with type INTEGER PRIMARY KEY is an alias for the ROWID (except in WITHOUT ROWID tables) which is always a 64-bit signed integer.
It is all explained in SQLite 3 documentation:
2.0 The INTEGER PRIMARY KEY
One exception to the typelessness of SQLite is a column whose type is INTEGER PRIMARY KEY. (And you must use "INTEGER" not "INT". A column of type INT PRIMARY KEY is typeless just like any other.) INTEGER PRIMARY KEY columns must contain a 32-bit signed integer. Any attempt to insert non-integer data will result in an error.
INTEGER PRIMARY KEY columns can be used to implement the equivalent of AUTOINCREMENT. If you try to insert a NULL into an INTEGER PRIMARY KEY column, the column will actually be filled with an integer that is one greater than the largest key already in the table. Or if the largest key is 2147483647, then the column will be filled with a random integer. Either way, the INTEGER PRIMARY KEY column will be assigned a unique integer. You can retrieve this integer using the sqlite_last_insert_rowid() API function or using the last_insert_rowid() SQL function in a subsequent SELECT statement.
Yes, there is a difference: INTEGER is a special case in SQLite, when the database does not create a separate primary key, but reuses the ROWID column instead. When you use INT (or any other type that "maps" to INTEGER internally) a separate primary key is created.
That is why you see sqlite_autoindex created for the INT primary key, and no index created for the one of type INTEGER: SQLite reuses a built-in indexing structure for the integer primary key, rendering the autoindex unnecessary.
That is why the INTEGER primary key is more economical, both in terms of storage and in terms of performance.
See this link for details.
Just to add albeit implied already on the answers here. The INTEGER PRIMARY KEY column that you created is simply an alias for ROWID or _ROWID_ or OID. And if the AUTOINCREMENT keyword is added then every new record inserted is an increment of 1 of the last ROWID and the last ROWID is kept by an sqlite internal table named sqlite_sequence.
See link here and here
On the other hand if you declare a column as INT PRIMARY KEY sqlite create an automatic index (hence the sqlite_autoindex) to keep track of the value inserted in the primary key to make sure it is unique.
Can we have an Array field as a Foreign Key? For example, I have following two Tables :
Create Sequence Product_id_seq start with 1 increment by 1;
Create Table Purchase (
Productid integer default next value for product_id_seq,
Qty integer,
cost decimal(17,2)
);
Create Sequence InvoiceNo_seq start with 1 increment by 1;
Create Table Sales (
Invoice_Number integer default next value for InvoiceNo_Seq,
qty integer,
product_ids ARRAY,
sale_value decimal(17,2)
);
I would like to add a constraint in table Sales such as "Foreign Key (Product_ids) references Purchase (Productid)".
Why?
eg. I purchased 20 Calculators on 1st July and Another 10 on 10th July. I sold 25 Calculators on 13th July, I should be able to point to the Productids of both the lots of Calculators, combining which they become 25 Nos (20 from productid 1 and 5 from productid 2). this is where array comes into picture.
I Just want to make sure that the Array Contains Values which are present in Purchase.ProductId.
Can this be Achieved?
You can achieve this using Trigger