Writing an SQL relation? - sql

A collection of puzzles is classified as 'easy', 'moderate' or 'challenging'. Each puzzle belongs to exactly one class. Here is a simplified version of the puzzle relation:
Student{puzzle_number:integer, description:text, class:text}
Write an SQL definition for this relation. Your definition should include a primary key constraint on puzzle_number and a check constraint at table level to enforce the requirement that the value of 'class' is one of 'easy', 'moderate' or 'challenging'
I am unsure what is meant by an SQL definition? Does it mean a create table statements?

Based on the context, I would assume it means to write a "CREATE TABLE" statement that includes table name, column names, their corresponding data types, as well as the constraint mentioned, that could be used to store data that would be used to hydrate the class. So for example, the table definition must be able to store a row that has columns such as (202, "Rubik's Cube", "moderate") that represent the puzzle_number, description, and class respectively.
You can enforce the constraint mentioned by using a foreign key to a second table that stores the puzzle classifications, or you can use a check constraint when defining the table to make sure it holds one of the 3 values allowed without having to use a second table.
Simple Create Table reference:
http://www.w3schools.com/sql/sql_check.asp
Simple Check constraint reference:
http://www.w3schools.com/sql/sql_check.asp

Related

What is the difference between key and constraint in sql?

I have referred many documents but couldn't find a supporting/compromising answer for this. Can anyone briefly describe the difference between key and constraints?
A key is a single or combination of multiple fields in a table. Its is used to fetch or retrieve records/data-rows from data table according to the condition/requirement. Keys are also used to create relationship among different database tables or views.
SQL constraints are used to specify rules for the data in a table.
If there is any violation between the constraint and the data action, the action is aborted.
Constraints can be specified when the table is created (inside the CREATE TABLE statement) or after the table is created (inside the ALTER TABLE statement).
you can check more documentation in the links below
Keys
Constraint

PostgreSQL - Modify CREATE TABLE syntax in an extension

Is it possible to write an PostgreSQL extension that modifies the DDL syntax?
I'm creating an extension on top of PostgreSQL and PostGIS to support integrity constraints of a specific spatial data model (OMT-G). For that, I want to modify the CREATE TABLE syntax, which accept CONSTRAINTS with this syntax:
CONSTRAINT constraint_name CHECK ( expression )
But I want to create my own syntax, like those in the following example, which will then call functions or triggers I have written already.
CREATE TABLE school_district (
id integer PRIMARY KEY,
school_name varchar(120)
geom geometry,
SPATIAL_CONSTRAINT PLANAR_SUBDIVISION (geom),
SPATIAL_CONSTRAINT CONTAINS school (geom)**
);
Is that possible? If so, how?
As others have commented, it's not possible to alter Postgres grammar via an extension. There's been some discussion related to this on the hacker's mailing list, but no one sees any feasible way to make the Bison grammar extensible.
The other problem with what you're proposing is that CHECK constraints (which it appears is what you're trying to do here) can not safely reference other tables.
It sounds like what you really want here is extensible foreign key support. That's something the community would actually like as well, at least for arrays. The idea is to support something like int[], where each element should be treated as a foreign key reference to another table. What you're describing is similar: instead of a different data type, you want to use a different operator.
For now though, I think the best you could do is to provide your users a function that will put an appropriate column and trigger on the table. The column would be a foreign key to the school table. The trigger would find an appropriate school and populate it's primary key in the new column. (You'd probably want a BEFORE DELETE trigger on the school table to deal with deleting a school too.)
The reason you need the foreign key field is because foreign key triggers operate with different visibility rules than normal queries, so you can't fully simulate them in user space. If you're not quite that paranoid you could just have a single AFTER INSERT trigger that looks for a school and throws an error if it doesn't find one.
As far as any pure-DDL solutions, the most promising method is using CREATE TABLE ... CONSTRAINT ... EXCLUDE, which operates GiST on a single table, and has relatively limited operators that work only on the bounding box (e.g. &&):
CREATE TABLE polygons (
geom geometry(Polygon,4326),
EXCLUDE USING gist (geom WITH &&)
);
INSERT INTO polygons(geom)
VALUES('SRID=4326;POLYGON ((0 0, 0 1, 1 0, 0 0))');
But then, this conflicts (even though the geometries don't actually overlap):
INSERT INTO polygons(geom)
VALUES('SRID=4326;POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))');
ERROR: conflicting key value violates exclusion constraint "polygons_geom_excl"
DETAIL: Key (geom)=(0103000020E61000000100000005000000000000000000F03F000000000000F03F000000000000F03F0000000000000040000000000000004000000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F) conflicts with existing key (geom)=(0103000020E61000000100000004000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000000000000000000000000000000000000000).
As mentioned above by #Jim, the best approach to have one table to build a constraint over another table is to make a good trigger function, and use it on both tables. It would normally be written in PL/pgSQL, where you can embed useful messages, such as:
RAISE EXCEPTION 'School % is not located in school district % (it is % away)',
s.name, d.name, ST_Distance(s.geom, d.geom);
This way, if you edit either the school_district or schools table, the trigger would to the check on UPDATE, INSERT, or DELETE to see if the conditions remain valid.

is it necessary to have foreign key for simple tables

have a table called RoundTable
It has the following columns
RoundName
RoundDescription
RoundType
RoundLogo
Now the RoundType will be having values like "Team", "Individual", "Quiz"
is it necessary to have a one more table called "RoundTypes" with columns
TypeID
RoundType
and remove the RoundType from the rounds table and have a column "TypeID" which has a foreign key to this RoundType table?
Some say that if you have the RoundType in same table it is like hard-coding as there will be lot of round types in future.
is it like if there are going to be only 2-3 round types, i need not have foreign key??
Is it necessary? Obviously not. SQL works fine either way. In a properly defined database, you would do one of two things for RoundType:
Have a lookup table
Have a constraint that checks that values are within an agreed upon set (and I would put enums into this category)
If you have a lookup table, I would advocate having an auto-incremented id (called RoundTypeId) for it. Remember, that in a larger database, such a table would often have more than two columns:
CreatedAt -- when it was created
CreatedBy -- who created it
CreatedOn -- where it was created (important for distributed systems)
Long name
In a more advanced system, you might also need to internationalize the system -- that is, make it work for multiple languages. Then you would be looking up the actual string value in other tables.
is it like if there are going to be only 2-3 round types, i need not
have foreign key??
Usually it's just the opposite: If you have a different value for most of the records (like in a "lastName" column) you won't use a lookup table.
If, however, you know that you will have a limited set of allowed/possible values, a lookup table referenced via a foreign key is probably the better solution.
Maybe read up on "database normalization", starting perhaps # Wikipedia.
Actually you need to have separate table if you have following association between entities,
One to many
Many to many
because of virtue of these association simple DBMS becomes **R**DBMS ( Relation .)
Now ask simple question,
Whether my single record in round table have multiple roundTypes?
If so.. Make a new table and have foreign key in ROUNDTable.
Otherwise no.
yeah I think you should normalize it. Because if you will not do so then definitely you have to enter the round types (value) again and again for each record which is not good practice at all in case if you have large data. so i will suggest you to make another table
however later on you can make a view to get the desired result as fallow
create view vw_anyname
as
select RoundName, RoundDescription , RoundLogo, RoundType from roundtable join tblroundtype
on roundtable.TypeID = tblroundtype .typeid
select * from vw_anyname

Can a foreign key have a constant instead of a field name? Relate FK to STI subclass

Setup
So here's a scenario which I'm finding is rather common once you decide to play with STI (Single Table Inheritance).
You have some base type with various subtypes.
Person < (Teacher,Student,Staff,etc)
User < (Member,Admin)
Member < (Buyer,Seller)
Vehicle < (Car,Boat,Plane)
etc.
There are two major approaches to modelling that in the database:
Single Table Inheritance
One big table with a type field and a bunch of nullable fields
Class Table Inheritance
One table per type with shared PK (FK'd from the children to the parent)
While there are several issues with STI, I do like how it manages to cut down on the number of joins you have to make, as well as some of the support in frameworks like Rails, but I am running into an issue on how to relate subclass-specific tables.
For example:
Certifications should only reference Teacher-Persons
Profiles should only reference Member-Users
WingInformation should be not be related to a car or boat (unless you are Batman maybe)
Advertisements are owned by Seller-Members not Buyer-Members
With CTI, these relationships are trivial - just slap a Foreign Key on the related table and you're done:
ALTER TABLE advertisements
ADD FOREIGN KEY (seller_id) REFERENCES sellers (id)
But with STI, the similar thing wouldn't capture the subtype restriction.
ALTER TABLE advertisements
ADD FOREIGN KEY (seller_id) REFERENCES members (id)
What I would like to see is something like:
* Does not work in most (all?) databases *
ALTER TABLE advertisements
ADD FOREIGN KEY (seller_id, 'seller') REFERENCES members (id, type)
All I have been able to find is a dirty hack requiring adding a computed column to the related table:
ALTER TABLE advertisements
ADD seller_type VARCHAR(20) NOT NULL DEFAULT 'seller'
ALTER TABLE advertisements
FOREIGN KEY (seller_id, seller-type) REFERENCES members (id, type)
This strikes me as odd (not to mention inelegant).
The real questions
Is there a RDBMS out there which will allow me to do this?
Is there a reason why this isn't even possible?
Is this just one more reason why NOT to use STI except in the most trivial of cases?
There's no standard way to declare a constant in the foreign key declaration. You have to name columns.
But you could force the column to have a fixed value, using one of the following methods:
Computed column
CHECK constraint
Trigger before INSERT/UPDATE to overwrite any user-supplied value with the default value.

Oracle Database Enforce CHECK on multiple tables

I am trying to enforce a CHECK Constraint in a ORACLE Database on multiple tables
CREATE TABLE RollingStocks (
Id NUMBER,
Name Varchar2(80) NOT NULL,
RollingStockCategoryId NUMBER NOT NULL,
CONSTRAINT Pk_RollingStocks Primary Key (Id),
CONSTRAINT Check_RollingStocks_CategoryId
CHECK ((RollingStockCategoryId IN (SELECT Id FROM FreightWagonTypes))
OR
(RollingStockCategoryId IN (SELECT Id FROM LocomotiveClasses)))
);
...but i get the following error:
*Cause: Subquery is not allowed here in the statement.
*Action: Remove the subquery from the statement.
Can you help me understanding what is the problem or how to achieve the same result?
Check constraints are very limited in Oracle. To do a check like you propose, you'd have to implement a PL/SQL trigger.
My advise would be to avoid triggers altogether. Implement a stored procedure that modifies the database and includes the checks. Stored procedures are easier to maintain, although they are slightly harder to implement. But changing a front end from direct table access to stored procedure access pays back many times in the long run.
What you are trying to is ensure that the values inserted in one table exist in another table i.e. enforce a foreign key. So that would be :
CREATE TABLE RollingStocks (
...
CONSTRAINT Pk_RollingStocks Primary Key (Id),
CONSTRAINT RollingStocks_CategoryId_FK (RollingStockCategoryId )
REFERENCES FreightWagonTypes (ID)
);
Except that you want to enforce a foreign key which references two tables. This cannot be done.
You have a couple of options. One would be to merge FreightWagonTypes and LocomotiveClasses into a single table. If you need separate tables for other parts of your application then you could build a materialized view for the purposes of enforcing the foreign key. Materialized Views are like tables and can be referenced by foreign keys. This option won't work if the key values for the two tables clash.
Another option is to recognise that the presence of two candidate referenced tables suggests that RollingStock maybe needs to be split into two tables - or perhaps three: a super type and two sub-type tables, that is RollingStock and FreightWagons, Locomotives.
By the way, what about PassengerCoaches, GuardsWagons and RestaurantCars?
Oracle doesn't support complex check constraints like that, unfortunately.
In this case, your best option is to change the data model a bit - add a parent table over FreightWagonTypes and LocomotiveClasses, which will hold all the ids from both of these tables. That way you can add a FK to a single table.