difference between key column and non key one - sql

Sorry for the newbie question.
I have define a table in a following way
CREATE TABLE `class1` (
`name` varchar(20) NOT NULL,
`familyname` varchar(20) NOT NULL,
`id` int(11) DEFAULT NULL,
KEY `class1` (`name`,`familyname`));
Can you explain me what is the difference here that i have here a name and family name as key.
I have to enter values to the table and run queries but i can't understand what it gives me ? If i not define name and family name as keys i get the same results .

A key, otherwise known as an index, will not change the results of a query, but sometimes it can make the query faster.
If you're interested, you can read about different kinds of keys here.

The KEY keyword in the create table syntax in mysql is a synonym for INDEX and will create an index on the 'name', 'familyname' columns.
This will not effect any constrains on the table but will make a query on the table faster when using the 'name' and 'familyname' columns in the where clause of a select statement.
If you wanted to create a primary key on those 2 columns you should use:
CREATE TABLE `class1` (
`name` varchar(20) NOT NULL,
`familyname` varchar(20) NOT NULL,
`id` int(11) DEFAULT NULL,
PRIMARY KEY (`name`,`familyname`));
This will stop you being able to insert multiple rows with the same 'name' and 'familyname' combination.

If you want to get data from your table, based upon the key or index fields (as said above), your query will execute faster, because the table will keep indexes about those values.
But, there is a downside to this as well. Adding unneeded indexes will have a negative effect on your performance. So to sum this all up: Indexes can speed up your database, but always check if they are really needed before adding them.

Related

SQL: How to link two tables that don't share a column name without creating a composite table?

I have to create a database named "Elections" and then write some queries to get the answers provided by my teacher.
I created the database. My issue is that I don't know how to link two tables (candidate and constituency) because they do not share any primary or foreign key.
The teacher is saying that a composite table should not be created in order to link those two tables.
Please see picture (the tables are linked on the pictures but I do not know how to do it when I create the database).
I am also including:
the query that I have to write. The thing is, without knowing how to link those two tables, I cannot write the query.
the SQL code representing the creation of those two tables.
QUERY:
1. Display the number of candidates eliminated in the first
round, for each constituency, and show the constituency number,
and name.
SQL CODE:
CREATE TABLE CANDIDATE (
CANDIDATE_NB smallint CONSTRAINT PK_CANDIDATE_NB PRIMARY KEY NOT NULL,
PARTY_NB smallint NOT NULL,
ROUND tinyint NOT NULL
);
alter table CANDIDATE ADD CONSTRAINT FK_PARTY_NB FOREIGN KEY (PARTY_NB) REFERENCES PARTY(PARTY_NB);
CREATE TABLE CONSTITUENCY (
CONSTITUENCY_NB smallint IDENTITY (100, 100) CONSTRAINT PK_CONSTITUENCY_NB PRIMARY KEY NOT NULL,
CONSTITUENCY_NAME varchar(20) NOT NULL,
NB_REGISTERED smallint NULL,
TOTAL_CANDIDATES smallint NULL
);
I am trying to understand how to link those two tables but I really can't think of anything apart from creating a composite table, which is not what has to be done as per my teacher's instructions.

Use a unique varchar as reference to a foreign key

Warning: possible duplicate
Hi,
I have the following table
CREATE TABLE names (
id uuid DEFAULT uuid_generate_v4(),
name VARCHAR(10) NOT NULL UNIQUE,
PRIMARY KEY (id)
);
Now, uuid basically says, use a unique VARCHAR(10) as an index. The question that I have is: can't I just use name as an id, since it's unique anyway and takes up the same amount of space or would this have negative impact on foreign keys?
I'm not new to SQL, I've just never came across this conflict and now I'm wondering if I've been using some concepts wrong the whole time.

Make a hint to SQLite that a particular column is always sorted

I have the following table in an SQLite database
CREATE TABLE `log` (
`time` REAL NOT NULL DEFAULT CURRENT_TIMESTAMP,
`data` BLOB NOT NULL
) WITHOUT ROWID;
CREATE INDEX `time_index` ON `log`(`time`);
The index is created because the most frequent query is going to be
SELECT * FROM `log` WHERE `time` BETWEEN ? AND ?
Since the time is going to be always the current time when the new record is added, the index is not really required here. So I would like to "tell" the SQLite engine something like "The lines are going to be added with the 'time' column always having increasing value (similar to AUTO_INCREMENT), and if something goes wrong I will take all responsibility".
Is it possible at all?
You don't want a separate index. You want to declare the column to be the primary key:
CREATE TABLE `log` (
`time` REAL NOT NULL DEFAULT CURRENT_TIMESTAMP PRIMARY KEY,
`data` BLOB NOT NULL
) WITHOUT ROWID;
This creates a single b-tree index for the log based on the primary key. In other databases, this structure would be called a "clustered index". You have probably already read the documentation but I'm referencing it anyway.
You would have an issue, or not depending upon how you consider that you cannot use :-
CREATE TABLE `log` (
`time` REAL NOT NULL DEFAULT CURRENT_TIMESTAMP,
`data` BLOB NOT NULL
) WITHOUT ROWID;
because :-
Every WITHOUT ROWID table must have a PRIMARY KEY. An error is raised
if a CREATE TABLE statement with the WITHOUT ROWID clause lacks a
PRIMARY KEY.
Clustered Indexes and the WITHOUT ROWID Optimization
So you might as well make the time column the PRIMARY KEY.
but the problem is that the precision of REAL is not enough to handle
microsecond resolution, and thus two adjacent records may have the
same time value which would violate the PRIMARY KEY constraint.
Then you could use a composite PRIMARY KEY where the precision required is satisfied by multiple columns (a second column would likely more than suffice) perhaps along the lines of :-
CREATE TABLE log (
time_datepart INTEGER,
time_microsecondpart,
data BLOB NOt NULL,
PRIMARY KEY (time_datepart,time_microsecondpart)
) WITHOUT ROWID;
The time_microsecondpart column needn't necessarily be microseconds it could be a counter derived from another table similar to how the sqlite_sequence table is utilised when AUTOINCREMENT is utilised (less the need for the column that holds the name of the table that a row is attached to).

Can a Unique constraint on multiple Columns add indexes separately on those columns

I have a table with structure shown below :-
CREATE TABLE IF NOT EXISTS tblvideolikes (
itemid SERIAL PRIMARY KEY,
videoid integer NOT NULL,
userid integer NOT NULL,
CONSTRAINT liked_video_user UNIQUE(videoid,userid)
)
I have a lot of select queries with userid and videoid. I want to know whether adding unique constraint on both columns are sufficient or Do I need to do indexing on both of them as well. I have searched a lot about this but nothing makes it clear.
If you have to enforce the unique combination of both columns, you have to create the unique index on both of them.
Postgres will use that index as well if your where clause only has a condition on the first column of the index (the usual "it depends" on index usage still applies here).
Postgres is able to use a column that is not the leading column of an index for a where condition - however that is less efficient then using a leading column.
I would put that column first that is used more often as single where condition. The order of the columns does not matter for the uniqueness.
If the usage of (only) the second column is as frequent as using the (only) first column, then adding an additional index with only the second column could make sense, e.g.:
CREATE TABLE IF NOT EXISTS videolikes (
itemid SERIAL PRIMARY KEY,
videoid integer NOT NULL,
userid integer NOT NULL,
CONSTRAINT liked_video_user UNIQUE(videoid,userid)
);
create index on videolikes (userid);
The unique index would then be used for conditions on only videoid and (equality) conditions using both columns. The second index would be used for conditions on only the userid
Unrelated, but:
The itemid primary key is pretty much useless with the above setup. You needlessly increase the size of the table and add another index that needs to be maintained. You can simply leave it out and declare videoid, userid as the primary key:
CREATE TABLE IF NOT EXISTS videolikes (
videoid integer NOT NULL,
userid integer NOT NULL,
CONSTRAINT pk_videolikes primary key (videoid,userid)
);
create index on videolikes (userid);
Indexing on both the column separately is a better idea if you are going to do frequent queries from both sides.

MySQL - Prevent duplicate records in table via index?

Using MySQL 5
I have a table like this:
date (varchar)
door (varchar)
shift (varchar)
route (varchar)
trailer (varchar)
+ other fields
This table contains user generated content (copied in from another 'master' table) and to prevent the users from creating the same data more than 1x the table has a unique index created based on the fields specified above.
The problem is that the "duplicate prevention" index doesn't work.
Users can still add in duplicate records with no errors being reported.
Is this problem due to my not understanding something about how indexes work?
Or
Is it a possible conflict with the primary key field (autoincrementing int)?
The CREATE TABLE looks like this:
CREATE TABLE /*!32312 IF NOT EXISTS*/ "tableA" (
"Date" varchar(12) default NULL,
"door" varchar(12) default NULL,
"Shift" varchar(45) default NULL,
"route" varchar(20) default NULL,
"trailer" varchar(45) default NULL,
"fieldA" varchar(45) default NULL,
"fieldB" varchar(45) default NULL,
"fieldC" varchar(45) default NULL,
"id" int(10) unsigned NOT NULL auto_increment,
PRIMARY KEY ("id"),
UNIQUE KEY "duplicate_preventer" ("Date","door","Shift","route","trailer"),
A row duplicated is:
date door shift route trailer
10/4/2009 W17 1st Shift TEST-01 NULL
10/4/2009 W17 1st Shift TEST-01 NULL
Users can still add in duplicate records with no errors being reported.
What do you mean by "duplicate records"?
Depending on collation, case, accent etc. may matter, and 'test' and 'TEST' will not be considered duplicates.
Could you please post the results of SHOW CREATE TABLE mytable?
Also, could you please run this query:
SELECT date, door, shift, route, trailer
FROM mytable
GROUP BY
date, door, shift, route, trailer
HAVING COUNT(*) > 1
If it returns the rows, the problem is with the index; if it does not, the problem is with your definition of a "duplicate".
Update:
Your columns allow NULLs.
NULL values in MySQL are not considered duplicate from the point of view of a UNIQUE index:
CREATE TABLE testtable (door VARCHAR(20), shift VARCHAR(15), UNIQUE KEY (door, shift));
INSERT
INTO testtable
VALUES
('door', NULL),
('door', NULL);
SELECT door, shift
FROM testtable
GROUP BY
door, shift
HAVING COUNT(*) > 1;
From documentation:
A UNIQUE index creates a constraint such that all values in the index must be distinct. An error occurs if you try to add a new row with a key value that matches an existing row. This constraint does not apply to NULL values except for the BDB storage engine. For other engines, a UNIQUE index allows multiple NULL values for columns that can contain NULL. If you specify a prefix value for a column in a UNIQUE index, the column values must be unique within the prefix.
Are you sure that you are using unique index instead of a normal index?
create unique index uix on my_table (date, door, shift, route, trailer);
Also that kind of index only makes sure that combination of fields is unique, you can for example have several duplicate dates if, for example, field door is different on every row. The difference could something that is hard to spot, for example a space in end of the value or lowercase/uppercase difference.
Update: your unique index seems to be in order. The problem is elsewhere.
I think you'd want to create a unique constraint on the fields you don't want duplicated. This will in turn create a unique index.
Like this:
ALTER TABLE YourTable
ADD CONSTRAINT uc_yourconstraintname UNIQUE (date, door, shift, route, trailer)