What data type to use for ratings in PostgreSQL - sql

I am making a table right now, and I'm confused about what to use, because I used to use smallint(6) but it doesn't work in PostgreSQL.

If the column can only have integer values between 1 and 5 you can use a SMALLINT for it with a CHECK constraint.
For example:
create table review (
rating smallint not null check (rating between 1 and 5)
);
The NOT NULL constraint ensures the column always has values.
The CHECK constraint ensures values are always between 1 and 5, and that, for example, a value 6 won't be accepted.

Related

Column type to store 0..7 (octal) and bool values (oracle, postgres)

I create a table in Oracle and I need to make a single column with the following values 0, 1, .., 6, 7
CREATE TABLE "LOC_DB"."TI_TS" (
"BIT" CHAR(1) CONSTRAINT cons_ti_ts_bit CHECK (BIT IN
('0','1','2','3','4','5','6','7'))
)
This was the only one best way? Or, maybe, we've got special types(octal number system)
(In case of PostgreSQL question interests too)
Edit 1
I was told that this practice is better:
CREATE TABLE "LOC_DB"."TI_TS" (
"BIT" NUMBER(1,0) NOT NULL CONSTRAINT const_ti_ts_bit CHECK (BIT between 0 and 7),
"ACTIV" NUMBER(1,0) NOT NULL CONSTRAINT const_ti_ts_active CHECK (ACTIV in (0,1)),
)
Thanks to Matt Allwood, a_horse_with_no_name

Difference between SQL keywords

I have just started with SQL and want to clear the basic keywords of SQL.
What is the difference between
"number" and "numeric" & "number & integer"?
While creating a table
Create table myTable
(
my_Id int(6) primary key
...
Above query Gives me an error suggesting to put null or not null before "primary key".
Do I always need to put either null or not null for the keyword integer?
If I replace int(6) with number(6), that statement works.
1."number" and "numeric" & "number & integer"?
An integer cannot take inputs such as 1.1 and the likes since float or decimal datatype handles this, while a number can take this both. I believe the reason why INT does not display it with a decimal its because its being rounded off try to input a 1.5 on an int column and you'll get a 2 instead
2.While creating a table
Create table myTable (
my_Id int(6) primary key, <--- Gives me an error suggesting to put
null or not null before "primary key". Do I always need to put either
null or not null for the keyword integer?
you need to either put a null or not null before a primary key unless I believe its been set into an Auto Increment
BTW my answer was based on MYSQL since that's what I used.. although I'm not sure if your using it since you didn't add any tags :)
for more info for this topic I think this could add a little more light to your inquiry
reference link
In MYSQL a primary key has to be a non-null value ie you will have to indicate by typing in NOT NULL You can re-write the code as follows:
my_id INT([optional]) PRIMARY KEY NOT NULL
When you want to make a Primary Key field it shouldn't be Null.
And
When you use int data type it don't have any (<value>), But number has.
SO
my_Id int not null primary key

Create a column with an if condition in SQL server

i am not sure if i could use conditional statement while creating new columns.
Code:
create table Employees(
Emp_ID int primary key identity (1,1),
Hours_worked int,
Rate int default '')
/*Now here in default value i want to set different rates depending upon hours worked. like if hour worked is greater than 8 then rate is 300, if hours worked is less than 8 hour the rate is 200.) How to write this as a Default value in sql server 2008.
My second question is:
Why i get error if i write like this,
create table tbl_1(
col_1 varchar(max) unique
)
The error is
Column 'col_1' in table 'tbl_1' is of a type that is invalid for use as a key column in an index.
Msg 1750, Level 16, State 0, Line 1
Regards
Waqar
you can use COMPUTED Column, http://msdn.microsoft.com/en-us/library/ms191250.aspx
create table Employees(
Emp_ID int primary key identity (1,1),
Hours_worked int,
Rate as (case when Hours_worked > 8 then 300 else 200 end) persisted )
The default value cannot refer to any other column names. So the "default" value of Rate won't know the value of Hours_worked. You could handle it with a trigger or whatever is doing the actual inserting could contain this logic.
http://msdn.microsoft.com/en-us/library/ms173565(v=sql.100).aspx
You cannot but a UNIQUE constraint on a VARCHAR(MAX) field.

PL/SQL - Only one value for a person

I have the following table.
CLASS_HAS_STUDENTS (
PER_SSN INTEGER NOT NULL,
PER_YEAR INTEGER NOT NULL, /*These two are PKs for a student*/
SCHOOL_CODE INTEGER NOT NULL, /*PK for a school*/
CLASS_YEAR INTEGER NOT NULL,
CLASS_NUMBER INTEGER NOT NULL,
CLASS_TEACHTYPE CHAR(3) NOT NULL, /*These three are PKs for a class*/
STUDCLASS_STATUS CHAR(1) NOT NULL
constraint CKC_STUDCLASS_STATUS_CLASS_TI check (StudClass_Status IN ('E', 'Y', 'T', 'P', 'F')),
STUDCLASS_LISTNUMBER INTEGER NOT NULL,
STUDCLASS_ROLLNUMBER INTEGER NOT NULL
);
(This code lacks some minor constraints)
Now, I need a way to check that one PER_SSN/PER_YEAR (a person's PK) can only have one 'E' ("Enrolled") status. I can't do this with a trigger (given I'm selecting from the same table) and I don't know if I can do this with a check constraint (can I use COUNT() here?). Any help is appreciated.
You can create a function-based unique index to enforce this sort of thing. You can't create a constraint as such.
This takes advantage of the fact that Oracle b-tree indexes do not index NULL data so the index will only have entries for the rows where studclass_status is E.
CREATE UNIQUE INDEX idx_one_enrolled
ON class_has_students( CASE WHEN studclass_status = 'E'
THEN per_ssn
ELSE null
END,
CASE WHEN studclass_status = 'E'
THEN per_year
ELSE null
END );
I'm a little confused by your question. I'm guessing you either want to:
1) Prevent insert of more than one status per student (in which case a trigger would be appropriate)
or
2) Use a SELECT statement to find students already in the table, in which case you want to do something like:
SELECT PER_SSN, PER_YEAR, STUDCLASS_STATUS, COUNT(*)
FROM CLASS_HAS_STUDENTS
WHERE STUDCLASS_STATUS = 'E'
HAVING COUNT(*) > 1
GROUP BY PER_SSN, PER_YEAR, STUDCLASS_STATUS;
You should be able to do this with a partial unique index. To make sure you only have one enrolled class for every ssn this should work:
CREATE UNIQUE INDEX ssn_enrollments ON class_has_students(per_ssn)
WHERE studclass_status='E';
Note that this feature is not supported in all SQL implementations, but PostgreSQL has supported since at least version 8.

Constraints in SQL Database

I need to have a table in T-SQL which will have the following structure
KEY Various_Columns Flag
1 row 1 F
2 row_2 F
3 row_3 T
4 row_4 F
Either no rows, or at most one row can have the Flag column with the value T. My developer claims that this can be achieved with a check constraint placed on the table.
Questions:
Can such a constraint be placed on the database itself (ie an inter-row constraint) at the database level, rather than in business rules for updating or inserting rows
Is such a table in normal form?
Or would normal form require removing the Flag column, and instead (say) had another simple table or variable containing the value of row which had Flag=T, ie in the above case row=3.
1 No. A check constraint is per row. No other constraint will do this either.
You need one of:
a trigger (all versions)
indexed view with filter Flag = T, and unique index on Flag (SQL Server 2000+)
filtered index (SQL Server 2008)
2 Good enough
3 Overkill really. You're splitting the same data up to avoid one the solutions above. But using a one row table, FK for the ID columns, and a unique constraint on Flag
My developer claims that this can be
achieved with a check constraint
placed on the table.
SQL Server does not directly** support subqueries in CHECK constraints (a requirement for Full SQL-92; SQL Server is only compliant with Entry Level SQL-92, broadly speaking).
While there are almost certainly better ways of enforcing this constraint in SQL Server, purely out of interest it can indeed be achieved using a row-level CHECK constraint and a UNIQUE constraint e.g. here's one way:
CREATE TABLE YourStuff
(
key_col INTEGER NOT NULL UNIQUE,
Various_Columns VARCHAR(8) NOT NULL,
Flag CHAR(1) DEFAULT 'F' NOT NULL
CHECK (Flag IN ('F', 'T')),
Flag_key INTEGER UNIQUE,
CHECK (
(Flag = 'F' AND Flag_key = key_col)
OR
(Flag = 'T' AND Flag_key = NULL)
)
);
The issue here is that you will need to maintain the Flag_key column's values 'manually'. Replacing the column + CHECK with a calculated column would mean the values are maintained automatically:
CREATE TABLE YourStuff
(
key_col INTEGER NOT NULL UNIQUE,
Various_Columns VARCHAR(8) NOT NULL,
Flag CHAR(1) DEFAULT 'F' NOT NULL
CHECK (Flag IN ('F', 'T')),
Flag_key AS (
CASE WHEN Flag = 'F' THEN key_col
ELSE NULL END
),
UNIQUE (Flag_key)
);
** While SQL Server does not directly support subqueries in CHECK constraints, there is a workaround in some cases using a user defined function (UDF) e.g.
CREATE FUNCTION dbo.CountTFlags ()
RETURNS INTEGER
AS
BEGIN
DECLARE #return INTEGER;
SET #return = (
SELECT COUNT(*)
FROM YourStuff
WHERE Flag = 'T'
);
RETURN #return;
END;
CREATE TABLE YourStuff
(
key_col INTEGER NOT NULL UNIQUE,
Various_Columns VARCHAR(8) NOT NULL,
Flag CHAR(1) DEFAULT 'F' NOT NULL
CHECK (Flag IN ('F', 'T')),
CHECK (1 >= dbo.CountTFlags())
);
Note that the UDF approach won't work in every case and that caution is required. The important point is that UDF will be evaluated for each row affected (rather than at the SQL statement or transaction level, as you may expect). In this case, the constraint needs to be true for every row affected and therefore -- I think! -- it is safe. For more details, see Trouble with CHECK Constraints by David Portas.
Personally, I would simply use a second table to model Flag, which would only involve keys and a foreign key e.g.
CREATE TABLE YourStuff
(
key_col INTEGER NOT NULL UNIQUE,
Various_Columns VARCHAR(8) NOT NULL
);
CREATE TABLE YourStuffFlag
(
key_col INTEGER NOT NULL UNIQUE
REFERENCES YourStuff (key_col)
);
Is [my] table in normal form?
You should by aiming for Fifth normal form (5NF). Whether you have achieved this depends upon the design of Various_Columns. I do not believe that your Flag falls fowl of the requirements for 5NF and I do not see any update, delete or insert anomalies (which is the point of normalization but a 5NF design can still exhibit anomalies). That said, to switch the row that gets the flag attibute, my two-table design requires a single UPDATE statement while your single-table design requires two ;)