In Microsoft SQL Server 2014, how do I set another key when there's already a primary key in that table? - sql-server-2014-express

Apologies in advance that this is definitely a beginner issue; but I'm genuinely having trouble finding the solution.
In the chart linked here, I am told which columns must be linked to other tables. chart
However, I'm stumped with the Books table because it needs to have 2 keyed columns. One is the primary key (Book ID), which I've already set up. But the Title is also supposed to be keyed with the Book ID in the Book Copies table. I tried to specify Book ID as a foreign key that references the Title in Books and got an error message saying
No primary or candidate key are referenced in 'Books'
This is because I didn't know how to set Title as a key, since one already exists in that table. My table creation code for Books and Book Copies is shown below. The foreign key link doesn't work right now because I'm unsure how to reference a column that is not a primary key. If someone could help me out with how to set "Title" in "Books" as a non-primary key that can be referenced by "Book ID" in "Book Copies", I'd truly appreciate it.
Thanks!!
CREATE TABLE Books
(
Book_ID INT PRIMARY KEY NOT NULL IDENTITY (1,1),
Title VARCHAR(50) NOT NULL
Publisher_NAME VARCHAR(50) NOT NULL
CONSTRAINT fk_Publisher_Name
FOREIGN KEY REFERENCES Publisher(Publisher_Name)
ON UPDATE CASCADE ON DELETE CASCADE,
);
CREATE TABLE Book_Copies
(
Book_ID INT NOT NULL
CONSTRAINT fk_Title
FOREIGN KEY REFERENCES Books(Title) ON UPDATE CASCADE ON DELETE CASCADE,
Branch_ID VARCHAR(50) NOT NULL,
Number_Of_Copies INT NOT NULL
);

Related

How to add multiple items into a column SQLite3?

I don't want to use different python packages like pickle.
I also don't want to use multiple databases.
So, how do I add a list or a tuple into a column of a database?
I had a theory of adding a string that would be like '(val1, val2, val3)' and then use exec to put it into a variable but that is too far-fetched and there is definitely a better and more efficient way of doing this.
EDIT:
I'll add some more information on what I'm looking for.
I want to get (and add) lists with this type of info:
{'pet':'name','type':'breed/species_of_pet', 'img':img_url, 'hunger':'100'}
I want this dict to be in the pets column.
Each pet can have many owners (many-to-many relationship)
If you want to have a users table and each user can have pets. You'd first make a pets table.
create table pets (
id integer primary key,
name text not null,
hunger int not null default 0
);
Then it depends on whether a pet has only one owner (known as a one-to-many relationship) or many owners (known as a many-to-many relationship).
If a pet has one owner, then add a column with the user ID to the pets table. This is a foreign key.
create table pets (
id integer primary key,
-- When a user is deleted, their pet's user_id will be set to null.
user_id integer references users(id) on delete set null,
name text not null,
hunger int not null default 0
);
To get all the pets of one user...
select pets.*
from pets
where user_id = ?
To get the name of the owner of a pet we do a join matching each rows of pets with their owner's rows using pets.user_id and users.id.
select users.name
from users
join pets on pets.user_id = users.id
where pets.id = ?
If each pet can have many owners, a many-to-many relationship, we don't put the user_id into pets. Instead we need an extra table: a join table.
create table pet_owners (
-- When a user or pet is deleted, delete the rows relating them.
pet_id integer not null references pets(id) on delete cascade,
user_id integer not null references users(id) on delete cascade
);
We declare that a user owns a pet by inserting into this table.
-- Pet 5 is owned by users 23 and 42.
insert into pet_owners (pet_id, user_id) values (5, 23), (5, 42);
To find a user's pets and their name, we query pet_owners and join with pets to get the name.
select pets.*
from pet_owners
join pets on pet_owners.pet_id = pets.id
where user_id = ?
This might seem weird and awkward, and it is, but it's why SQL databases are so powerful and fast. It's done to avoid having to do any parsing or interpretation of what's in the database. This allows the database to efficiently query data using indexes rather than having to sift through all the data. This makes even very large databases efficient.
When you query select pets.* from pets where user_id = ?, because foreign keys are indexed, SQLite does not search the entire pets table. It uses the index on user_id to jump straight to the matching records. This means the database will perform the same with 10 or 10 million pets.
There is nothing stopping you from storing JSON or other array-like text in SQLite; it's just that it's much harder to query when you do so. SQLite does have facilities for manipulating JSON, but in general I would probably lean toward #Schwern's solution.

How to add a NOT NULL foreign key to SQlite3 table in node.js

I am having some trouble adding a foreign key column to an already existing table on SQLite.
Here's my SQL code:
CREATE TABLE IF NOT EXISTS director (
director_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS movie (
movie_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
);
ALTER TABLE movie ADD COLUMN director_id INTEGER NOT NULL REFERENCES
director(director_id);
This give me the following error:
Uncaught Error: Cannot add a NOT NULL column with default value NULL
However, if I remove the "NOT NULL" constraint it runs fine:
ALTER TABLE movie ADD COLUMN director_id INTEGER REFERENCES
director(director_id);
The following also works just fine but I already have an existing table:
CREATE TABLE IF NOT EXISTS director (
director_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS movie (
movie_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
director_id INTEGER NOT NULL,
FOREIGN KEY(director_id) REFERENCES director(director_id)
);
Am I missing something or it cannot be made in SQLite?
When altering a table to add a column with NOT NULL, you need to add a DEFAULT value. Otherwise, it has no idea what to put in an existing record when adding the column (since NULL is not valid).
Docs ref: https://sqlite.org/lang_altertable.html
For example:
CREATE TABLE IF NOT EXISTS movie (
movie_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
);
ALTER TABLE movie ADD COLUMN director_id INTEGER NOT NULL DEFAULT 0 REFERENCES director(director_id);

UNIQUE NONCLUSTERED INDEX - Insert Duplicate Values

I have a UNIQUE NONCLUSTERED INDEX on my Azure Database, code is below...
CREATE UNIQUE NONCLUSTERED INDEX [IX] ON [dbo].[TableName]
(
[Username] ASC,
[GUID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
For some reason there are duplicate values in the table on Username and GUID.
How is that possible if this index exist?
Can you turn it off and then on to add a new record with the same Username and GUID?
Getting the below error...
Cannot insert duplicate key row in object
'dbo.Tablename' with unique index
It's possible to disable the checking of constraints when inserting into a table with a UNIQUE index on it using the ALTER TABLE ... NOCHECK command. Inserts can be performed that violate the constraint, and then the constraint can be later re-enabled, leaving the duplicate records intact.
e.g.
USE AdventureWorks2012;
GO
ALTER TABLE Purchasing.PurchaseOrderHeader
NOCHECK CONSTRAINT FK_PurchaseOrderHeader_Employee_EmployeeID;
GO
(Reference link)
or
ALTER TABLE [MyTable] NOCHECK CONSTRAINT ALL
Related: How can foreign key constraints be temporarily disabled using T-SQL?

How to use static column in scylladb and cassandra?

I am new in scylladb and cassandra, I am facing some issues in querying data from the table, following is the schema I have created:
CREATE TABLE usercontacts (
userID bigint, -- userID
contactID bigint, -- Contact ID lynkApp userID
contactDeviceToken text, -- Device Token
modifyDate timestamp static ,
PRIMARY KEY (contactID,userID)
);
CREATE MATERIALIZED VIEW usercontacts_by_contactid
AS SELECT userID, contactID, contactDeviceToken,
FROM usercontacts
contactID IS NOT NULL AND userID IS NOT NULL AND modifyDate IS NOT NULL
-- Need to not null as these are the primary keys in main
-- table same structure as the main table
PRIMARY KEY(userID,contactID);
CREATE MATERIALIZED VIEW usercontacts_by_modifyDate
AS SELECT userID,contactID,contactDeviceToken,modifyDate
FROM usercontacts WHERE
contactID IS NOT NULL AND userID IS NOT NULL AND modifyDate IS NOT NULL
-- Need to not null as these are the primary keys in main
-- table same structure as the main table
PRIMARY KEY (modifyDate,contactID);
I want to create materialized view for contact table which is usercontacts_by_userid and usercontacts_by_modifydate
I need the following queries in case of when I set modifydate (timestamp) static:
update usercontacts set modifydate="newdate" where contactid="contactid"
select * from usercontacts_by_modifydate where modifydate="modifydate"
delete from usercontacts where contactid="contactid"
It is not currently possible to create a materialized view that includes a static column, either as part of the primary key or just as a regular column.
Including a static row would require the whole base table (usercontacts) to be read when the static column is changed, so that the view rows could be re-calculated. This has a significant performance penalty.
Having the static row be the view's partition key means that there would only be one entry in the view for all the rows of a partition. However, secondary indexes do work in this case, and you can use that instead.
This is valid for both Scylla and Cassandra at the moment.

Cassandra Composite Columns - How are CompositeTypes chosen?

I'm trying to understand the type used when I create composite columns.
I'm using CQL3 (via cqlsh) to create the CF and then the CLI to issue a describe command.
The Types in the Columns sorted by: ...CompositeType(Type1,Type2,...) are not the ones I'm expecting.
I'm using Cassandra 1.1.6.
CREATE TABLE CompKeyTest1 (
KeyA int,
KeyB int,
KeyC int,
MyData varchar,
PRIMARY KEY (KeyA, KeyB, KeyC)
);
The returned CompositeType is
CompositeType(Int32,Int32,UTF8)
Shouldn't it be (Int32,Int32,Int32)?
CREATE TABLE CompKeyTest2 (
KeyA int,
KeyB varchar,
KeyC int,
MyData varchar,
PRIMARY KEY (KeyA, KeyB, KeyC)
);
The returned CompositeType is
CompositeType(UTF8,Int32,UTF8)
Why isn't it the same as the types used when I define the table? I'm probably missing something basic in the type assignment...
Thanks!
The composite column name is composed of the values of primary keys 2...n and the name of the non-primary key column being saved.
(So if you have 5 non-key fields then you'll have five such columns and their column names will differ only in the last composed value which would be the non-key field name.)
So in both examples the composite column is made up of the values of KeyB, KeyC and the name of the column being stored ("MyData", in both cases). That's why you're seeing those CompositeTypes being returned.
(btw, the first key in the primary key is the partitioning key and its value is only used as the row key (if you're familiar with Cassandra under the covers). It is not used as part of any of the composite column names.)

Resources