Question about SQLite.
In the CREATE TABLE SQL, we can add UNIQUE constraints in either way: column-constraint or table-constraint. My question is simple. Do they work differently?
The only difference I could find was, in table-constraint, there could be multiple indexed-columns in a single constraint.
Column-constraint:
Table-constraint:
Here is an example:
CREATE TABLE Example (
_id INTEGER PRIMARY KEY,
name TEXT UNIQUE ON CONFLICT REPLACE,
score INTEGER
)
and
CREATE TABLE Example (
_id INTEGER PRIMARY KEY,
name TEXT,
score INTEGER,
UNIQUE (name) ON CONFLICT REPLACE
)
Are they different?
In this case there is no difference.
However, you could create an unique constraint on table, that would span over two different columns. Like this:
CREATE TABLE Example (
_id INTEGER PRIMARY KEY,
name TEXT,
index INTEGER,
score INTEGER,
UNIQUE (name, index) ON CONFLICT REPLACE
)
Consult this post for further details:
SQLite table constraint - unique on multiple columns
Related
I apologize for the bad title, but I wasn't sure how else to phrase it.
Let's imagine for a moment that I wanted to create a us_states table as follow:
create table us_states
(
id serial,
name varchar(256) not null constraint us_states_pk primary key,
code varchar(256) not null
);
What tangible benefits, if any, are there to having an auto incremental id column in a db_table if I don't plan on leveraging it as the primary key for said db_table?
There is zero value in adding an auto-incremented numerical column if it isn't a primary key or unique constraint.
If you have a unique column like name in your case, there are only two considerations not to use it as primary key:
storing a number instead of the name in tables that reference this one will save space
it is painful and should be avoided to modify primary key columns, so if the names change as part of the normal operation, it makes sense to use a different column as primary key
I am talking about the normalization of a primary key. So let's say my primary key column is of type nvarchar, which violates the rules of normalization. After removing the primary key constraint and the identity specification from the desired column. I need to create a new column which will be the new primary key of that table.
My question is, what should happen with the previous primary key?
I've got an answer that sounds like: "the column should became a semantic key", but i can't understand this answer.
It's not unusual when designing a database schema to use a SURROGATE primary key. The idea is to give each record a unique and permanent identifier so it can be easily referenced by applications and foreign keys. This key has no meaning. Knowing the surrogate key gives you no information about the content of the record. The user of your application would never see this value.
On the other hand, your record may have a SEMANTIC primary key. This is a unique value that identifies this data to that makes sense to the user.
For example, let's say you have a table of Employees. The employer assigns each employee a unique Employee ID Number. Let's say you store this value as a string. To the user that value serves as the unique identifier that refers to that employee. Meanwhile, your table may have a numeric column that serves as the unique identifier for that record.
create table Employee ( EmployeeRecordID int identity(1,1) primary key,
EmployerAssignedID nvarchar(12),
EmployeeName nvarchar(60),
Salary money )
insert into Employee ( EmployerAssignedID, EmployeeName, Salary ) values
( '#ABC100', 'Fred', 25000.12 ),
( '#AZZ314', 'Mary', 37700.00 ),
( '#MAA719', 'Fran', 34444.04 ),
( '#MZA977', 'Mary', 36000.00 )
As each record is added, SQL Server generates a unique EmployeeRecordID for each record, starting with 1. This is the SURROGATE key. Within your database and within your application, you would use this value to reference the record.
But when your application is communicating with the users, you would use the EmployerAssignedID. This is the SEMANTIC primary key. It makes sense to your users to use this value to search for a particular employee.
A primary key is no more than a unique index which can't have NULL value as a key. Like any of indexes it can be clustered or nonclustered.
Deleting a clustered index makes table become a heap with changes in structure and behaviour. Deleting a nonclustered index is just deallocation its space and does not affect that table and other indexes on the table as well.
So after deleting you just have a column(s) with unique values and you are able to consider them as a semantic key until some duplicate values are inserted.
I am trying to create a composite primary key in Sql server.
The syntax I have tried is:
create table Installment_details
(
constraint P_key primary key(Account_No,month),
Account_No int not null,
foreign key (Account_No) references Account_details(Account_no) on delete cascade,
Month char(15) not null,
D#te date,
Receipt_no varchar(15),
Amount_received int,
Amount_left int,
Amount_receiver char(50),
)
As far as I know it should create column with column name P_key for primary key but whenever I make a entry in table it doesn't show this column.
You are confused about the terms you're using. It's not the same a Primary Key and a Column. For example, you're creating a Primary Key based on two existing columns, and the name P_Key it's the name of the Primary Key, which is the way SQL SERVER (in this case) can identify a row in the Table (it cannot be two rows with the same values on those two columns).
I hope this clarifies a little bit the issue.
I think you are getting it wrong P_key in your code is constraint's name not a column name.
Also composite key is not a column, it is used when you don't have a column with unique values. So you take combination of two or more column as primary key so that we can uniquely identify a row.
I want to start off saying I am not a database guru, but I'm decent with the basics.
I have a set of IO data that I'm storing in two tables which are uniquely identified by 'ioid' and 'machinenum'.
I have a 2 tables: IOConfig which uniquely identifies points (all the identifying information and a primary key: ConfigID). And a data table that contains samples of these items.
My table layouts below are to test using a primary key + index versus using just an index, so I know there is duplicate data.
Think of IOConfig table as such:
ConfigId(PK) machineNum ioId ioType
Think of IOData table as such:
Timestamp ConfigId machineNum ioId value
If I use the ConfigID primary key, with an index on (timestamp,ConfigId) my query is like this:
select * from AnalogInput
where sampleTimestamp>=1520306916007000000 and sampleTimestamp<=1520351489939000000
and configId in (1112)
"0" "0" "0" "SEARCH TABLE IOData USING INDEX cfgIndexAnalogInput (configId=? AND sampleTimestamp>? AND sampleTimestamp<?)"
If I avoid using ConfigID the query is like this:
select * from AnalogInput
where sampleTimestamp>=1520306916007000000 and sampleTimestamp<=1520351489939000000
and ioId in (1)
and machineid=1111
"0" "0" "0" "SEARCH TABLE IOData USING INDEX tsIndexAnalogInput (sampleTimestamp>? AND sampleTimestamp<?)"
Why wouldn't I get the improvement that I see with the first query + Index of (timestamp,configid) for the second query using an index of (timestamp,machineNum,ioid)? I ask because machineNum and ioid are used to define what point is unique to make a configId primary key... so one would expect them to equate?
schema:
CREATE TABLE 'IOData'(
'sampleTimestamp' INTEGER,
'configId' INTEGER,
'machineId' INTEGER,
'ioId' INTEGER,
'value' REAL);
CREATE TABLE 'IOConfig'(
'sampleTimestamp' INTEGER,
'configId' INTEGER PRIMARY KEY,
'machineId' INTEGER,
'ioId' INTEGER,
'ioType' INTEGER);
CREATE INDEX `Something` ON `IOData` (`sampleTimestamp` ASC,`machineId` ASC,`ioId` ASC)
CREATE INDEX cfgIndexAnalogInput ON IOData(configId,sampleTimestamp)
CREATE INDEX tsIndexAnalogInput ON IOData(sampleTimestamp)
Read Query Planning to understand how indexes work, and The SQLite Query Optimizer Overview to see what specific optimization will be applied.
In this case, the filter on sampleTimestamp uses inequality comparisons, so, according to section 1.0, that must be the last column in the index (either in an explicit index, or in a three-column primary key):
CREATE INDEX SomethingBetter ON IOData(machineId, ioId, sampleTimestamp);
I'm having trouble figuring out how to create a foreign key constraint. My data model is fixed and out of my control, it looks like this:
CREATE TABLE Enquiry
(Enquiry_Ref INTEGER PRIMARY KEY CLUSTERED, Join_Ref INTEGER, EnquiryDate, EnquiryType...)
CREATE TABLE Contact
(Contact_Ref INTEGER PRIMARY KEY CLUSTERED, Surname, Forenames ....)
CREATE TABLE UniversalJoin
(Join_Ref INTEGER, Contact_Ref INTEGER, Rel_Type INTEGER)
Each Enquiry has exactly one Contact. The link between the two is the UniversalJoin table where
Enquiry.Join_Ref = UniversalJoin.Join_Ref AND
Rel_Type = 1 AND
UniversalJoin.Contact_Ref = Contact.Contact_Ref
The Rel_Type differs depending on what the source table is, so in the case of Enquiry, Rel_Type is 1 but for another table it would set to N.
My question is how do I create a foreign key constraint to enforce the integrity of this relationship? What I want to say, but can't, is:
CREATE TABLE Enquiry
...
CONSTRAINT FK_Foo
FOREIGN KEY (Join_Ref)
REFERENCES UniversalJoin (JoinRef WHERE Rel_Type=1)
You can't use conditional or filtered foreign keys in SQL Server
In these cases, you could have a multiple column FK between (JoinRef, Rel_Type) and set a check constraint on Rel_Type in UniversalJoin to make it 1.
However, I think you are trying to have a row with multiple parents which can't be done.
You might rather want to have a look at CHECK Constraints
CHECK constraints enforce domain
integrity by limiting the values that
are accepted by a column. They are
similar to FOREIGN KEY constraints in
that they control the values that are
put in a column. The difference is in
how they determine which values are
valid: FOREIGN KEY constraints obtain
the list of valid values from another
table, and CHECK constraints determine
the valid values from a logical
expression that is not based on data
in another column.
You could use a table trigger with INSERT and Update to layer the equivalent as a FK.
This way you are able to apply conditions i.e. if column value =1 check exists in table a if column value = 2 then check another table.