Insert a constraint for two columns in sql - database

Hi everyone I created this table for a database
CREATE TABLE IF NOT EXISTS compositions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
id_product INTEGER REFERENCES products(id),
id_receipt INTEGER REFERENCES receipt(id),
quantity INTEGER NOT NULL,
price FLOAT NOT NULL,
id_user VARCHAR REFERENCES users(id),
CONSTRAINT CHK_price_quantity CHECK (price > 0 AND quantity > 0)
);
I would like to insert a constraint that, for a given id_receipt, the id_user must be always the same but I don't know how to implement it.
Could someone give a help?
Thank you in advance.

For this requirement the column id_user should not be defined in the table compositions.
It makes more sense to store it in the table receipt, since each id_receipt is related to 1 and only 1 id_user.
This way you have id_receipt as a foreign key in compositions and through this column you can get (by a join) all the info that you want from receipt, like the id_user.

Related

Composite primary key in sql server

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.

MSSQL - Foreign key to the same column IF other column is not equal to the referring row

I have a database in which i have two tables:
CREATE TABLE Transactions (
ID BIGINT IDENTITY(1,1) NOT NULL,
AccountID BIGINT NOT NULL,
Amount BIGINT NOT NULL,
CONSTRAINT PK_Transactions PRIMARY KEY CLUSTERED (ID ASC,AccountID ASC),
CONSTRAINT FK_Transaction_Account FOREIGN KEY (AccountID) REFERENCES Accounts(ID)
);
CREATE TABLE Accounts (
ID BIGINT IDENTITY(1,11) NOT NULL,
Balance BIGINT NOT NULL,
CONSTRAINT PK_Accounts PRIMARY KEY (ID)
);
Transactions are inserted to their table by a stored procedure i wrote, so that two rows are generated when Account 1 transfers 25 "coins" to Account 21:
ID | AccountID | Amount
-------------------------
1 | 1 | -25
-------------------------
1 | 21 | 25
In the above schema, i want the first row to reference the bottom row based on ID and the AccountID being unequal to the AccountID of the bottom row.
And vica versa.
What i want to do would look something like this:
CONSTRAINT FK_Transaction_Counterpart FOREIGN KEY (ID) REFERENCES Transactions(ID) WHERE thisRow.AccountID != referencedRow.AccountID
I haven't found this possibility in the documentation on the table constraints.
So both out of curiosity and intent to use this i ask, is this possible? And if yes, how?
Edit:
Answers reflect that this is not possible, and i should adjust my design or intentions.
I think i will settle with assigning the two transaction rows to each other in the functional code.
A traditional foreign key can't be conditional (i.e. no WHERE clause attached). In your case, I'd probably just make sure that the inserts are atomic (in the same transaction) so that there'd be no possibility of only one of them inserting.
If the data model you are trying to implement is:
One transaction (ID) has two and only two entries in table Transactions
For the two rows of a given Transaction ID, the AccountIDs cannot be the same
Then one perhaps overly-complex way you could enforce this business rule within the database table structures would be as follows:
Table Accounts, as you have defined
Table Transactions, as you have defined
New table TransactionPair with:
Columns (all are NOT NULL)
ID
LowAccountID
HighAccountID
Constraints
Primary key on ID (only one entry per Transaction ID)
Foreign key on (ID, LowAccountID) into Transactions
Foreign key on (ID, HighAccountID) into Transactions
Check constraint on the row such that LowAccountID < HighAccountID
Process:
Add pair of rows to Transactions table
Add single row to TransactionPair referencing the rows just added
If that row cannot be added, something failed, roll everything back
Seems neat and tidy, but quite possibly overly complex. Your mileage may vary.

DB2: Attempting to reference Auto Generated Fields within Intersection Tables

I am working on a project using DB2 in attempt to create a small inventory system. Currently my team and I are looking for answers to a roadblock we have encountered where we are creating tables with auto generated fields. I have included a sample create statement to give you an understanding of what we are working with:
"CREATE TABLE INVENTORY (
PRODUCT_ID INT NOT NULL Generated always as identity (start with 1 increment by 1 minvalue 1 no maxvalue no cycle no cache order),
PRODUCT_NAME CHAR(100) NOT NULL,
DESCRIPTION CHAR(100),
UNIT_PRICE DECIMAL(6 , 2),
QUANTITY INTEGER
)
DATA CAPTURE NONE;
The issue we are coming across is when we insert test data into our database (no errors when we run the ddl; test data has no errors when we insert it) is that we can view the values of an auto generated field in the main table, but NOT in an intersection table where that value is used as a foreign key. An example of an intersection table that we are using in relation to our INVENTORY table is below:
CREATE TABLE RECEIVABLES (
ITEM_LINE INT NOT NULL Generated always as identity (start with 10 increment by 1 minvalue 10 no maxvalue no cycle no cache order),
PAYMENT_TYPE CHAR(15),
REMARKS CHAR(70),
RECEIVED_QUANTITY INTEGER,
VENDOR_ID CHAR(4) NOT NULL,
PRODUCT_ID INT,
SHIPMENT_ID INT
)
DATA CAPTURE NONE;
INSERT INTO RECEIVEABLES VALUES (DEFAULT,'DISCOVER','Success',9,'1000',DEFAULT,DEFAULT);
When we view the data, we are not seeing any NULL values; we simply aren't seeing ANY values for any of the foreign key fields in the intersection table (in this case, PRODUCT_ID and SHIPMENT_ID).
Is there a particular method to inserting data into an intersection table that will allow the values of the Primary keys to be represented in the intersection table as well?
Thank you very much for your time. I will be actively responding to any questions you may have
It takes more than naming a column the same to make it a foreign key. In fact, the name doesn't matter. What matters is defining a FK constraint over it:
CREATE TABLE RECEIVABLES (
ITEM_LINE INT NOT NULL Generated always as identity
(start with 10
increment by 1
minvalue 10
no maxvalue
no cycle
no cache order),
PAYMENT_TYPE CHAR(15),
REMARKS CHAR(70),
RECEIVED_QUANTITY INTEGER,
VENDOR_ID CHAR(4) NOT NULL,
PRODUCT_ID INT,
SHIPMENT_ID INT,
CONSTRAINT inv_fk FOREIGN KEY (product_id)
REFERENCES inventory (product_id),
CONSTRAINT shp_fk FOREIGN KEY (shipment_id)
REFERENCES shimpments (shipment_id)
) DATA CAPTURE NONE;
I would have expected to see null values in original table after your insert; since neither product_id nor shimpment_id in recieables is defined with NOT NULL. Running the same insert over the table I've posted you still give you NULL in the FK columns.
The generated ID is only generated in the primary table. You have to specify the value when inserting into into RECEIVABLES.
Now let's say you've just insert a row into INVENTORY and you want to insert a row referencing it into RECEIVABLES. Before the insert into RECEIVABLES, you have to ask the DB what the ID it generated for the row in INVENTORY.
The IDENTITY_VAL_LOCAL() function is one such way to do so...

two field in which one is degree Foreign key and study as null

I have two columns. SQL is:
CREATE TABLE tdegree
(
degree varchar(25) NOT NULL primary key
)
CREATE TABLE tstudy
(
study varchar(25) NOT NULL unique,
degree varchar(25) NOT NULL FOREIGN KEY REFERENCES tdegree (degree)
)
as shown in below figure I want to add record
master it
mphil it
but not
master it
master it
If I apply unique constraints on study field then it does not allowed me to add
master it
mphil it
Which constraints i have to apply?
If I understand correctly, you want the combination of study and degree to be unique, but values can be repeated in individual columns e.g. Row 1 is Master + IT and Row 2 is MPhil + IT, so that both rows are unique but study column has duplicate value IT. In that case, you need to add a unique constraint on both columns together like so:
alter table tstudy add constraint cunique unique(study,degree)
Note that you also need to change the definition of your tstudy table and remove the unique constraint on study column, otherwise you will get a unique constraint violation error, even after adding the above constraint:
CREATE TABLE tstudy
(
study varchar(25) NOT NULL,
degree varchar(25) NOT NULL FOREIGN KEY REFERENCES tdegree (degree)
)

Pledges table normalize

I have this table and I don't know how to normalize.
1st table name, address, landline no., mobile no., e-mail ad, amount, and registration number https://docs.google.com/file/d/0B99TeByt30n2dDVLVHV4dU1yRFE/edit
and in the second table will be their monthly pledges. https://docs.google.com/file/d/0B99TeByt30n2TVh4c1dmLTFYOWs/edit
PersonTable
PersonId int primary key
Name varchar(50)
Addresss varchar(50)
etc.
PledgeTable
PledgeId int primary key,
PersonId int foreign key references PersonTable(PersonId)
PledgeDate datetime
PledgeAmount decimal(10,2)
Ok.
You have to re engineer the whole idea.
I will give you a few concepts to understand what to do.
Keep in mind that we must NOT to have data duplicates.
So an array can be named Customer.
Customer can have a customer id column, named c_id for instance.
c_id must be defined as integer UNIQUE Auto_Increment NOT NULL
That means that it's an attribute that grants each customer its uniqueness.
A customer might have same name and same surname with another customer, but never same c_id.
Auto increment means that the first entry will be automatically numbered with c_id = 1, the next 2 etc etc.
Keep in mind that if you pass a record in the database using PHP, you enter null as value for c_id. Auto Incremet does the job then.
So you got a customer table and its first attribute that will be defined as the Primary key.
For example here is a small table:
CREATE TABLE customer
(c_id integer UNIQUE Auto_Increment NOT NULL,
c_name varchar(100),
c_surname varchar(100),
c_address varchar(100),
PRIMARY KEY (c_id)
);
You have to add all the attributes the customer has in the table.
That was just an example.
PRIMARY KEY (c_id) line in the end,
sets c_id as the primary key that distinguishes each record as unique.
Then you got another table.
A Pledge table.
CREATE TABLE pledge
(pl_id integer UNIQUE Auto_Increment NOT NULL,
pl_date date,
pl_price double(9,2),
pl_c_id integer,
PRIMARY KEY (pl_id),
FOREIGN KEY (pl_c_id) REFERENCES customer (c_id));
What is new here?
Line:
pl_c_id integer,
and line:
FOREIGN KEY (pl_c_id) REFERENCES customer (c_id)
What happens here, is that you create a column, that will contain an existing c_id!
That way, you make a reference to a customer, by using his/her UNIQUE c_id.
This is defined as integer, so it can fit the key.
pl_c_id MUST be the same type as the primary key of the other table. Ok?
Also SQL will know what key we refer to, by reading the line:
FOREIGN KEY (pl_c_id) REFERENCES customer (c_id)
In plain English that means:
pl_c_id can be filled with values already declared in a Primary Key of another Table, named "customer" that uses as primary key the column named "c_id".
Got it?
Now you got the flexibility to use ANY date.
That is more normalized than what you got.
Usually a 3NF (Third Normal Form) you will be ok.
Oh! Not to mention that you can Google "3NF" or "Third Normal Form" and get nice results for your reference.
;)
Cheers.
Edit: Made this reply more simple to understand.

Resources