How to test a CONSTRAINT in oracle - sql

I have the following constraint:
ALTER TABLE Movie
ADD CONSTRAINT NomsRANGE
CHECK (totalNoms BETWEEN 0 AND 20);
...and used the following to try and test it:
INSERT INTO Movie
(totalNoms)
VALUES
('23');
I get the following error:
cannot insert NULL into ("ALI"."MOVIE"."MOVIEID")
My scheme is:
Actor (actorID, lastName, firstName, middleName, suffix, gender, birthDate, deathDate)
Movie (movieID, title, year, company, totalNoms, awardsWon, DVDPrice, discountPrice)
Quote (quoteID, quote)
Role (roleID ,roleName ,gender ,actorID* ,movieID*)
RoleQuote (roleID*, quoteID*)
And my relationships are:
CONSTRAINT_NAME C
------------------------------ -
QUOTE_FK R
ROLE_FK R
MOVIE_ROLE_FK R
ACTOR_ROLE_FK R
ACTORID P
MOVIEID P
QUOTEID P
ROLEID P
ROLEQUOTEID P
9 rows selected.
Answer:
The answer was simple none of you spotted this it took me all day but i solved it so am posting solution so it helps others.
INSERT INTO Movie(movieID, totalNoms)
VALUES('049', '22');
I missed the first value which was the primary key as the error was saying:
cannot insert NULL into ("ALI"."MOVIE"."MOVIEID")
When i entered a new primary key it showed the constraint was violated
Thank you guys for all the help

If you omit columns in an INSERT statement, the database still needs to fill the column for that row. Which would be NULL, unless you setup a DEFAULT constraint/etc for each column.
The error is telling you that MOVIE.movieid does not accept NULL, which is good. It sounds like you need to setup the sequence to populate the value, or provide logic for however you want MOVIE.movieid populated (far less ideal). The sequence can either be referenced in the INSERT statement to fill the value, or you can look at triggers/default constraints to handle things in the background.
You'll have to figure out how you want/need to handle any other errors relating to column NULLability. Only after this is done, will you be able to see if your CHECK constraint works -- there's a little concern about if the value is provided as a string, if Oracle will implicitly convert it to an INT/NUMERIC data type.

1) The specific error is telling you that your INSERT statement needs to specify the MovieID. If you have created sequences to generate your synthetic primary key values, you'd want something like this (assuming there are no other NOT NULL columns in the Movie table)
INSERT INTO Movie
(movieID, totalNoms)
VALUES
(movieId_seq.nextval, 23);
2) Assuming that totalNoms is a NUMBER since your check constraint is treating it like a number, you would want to insert the number 23 rather than the string 23. Forcing Oracle to do implicit conversions is never a good idea-- it probably won't matter on a simple INSERT like this but if you get in the habit of using numbers when you're dealing with numeric fields and strings when you're dealing with character fields, life will be a lot easier.

Related

Append query error

My primary key of Specialization table is complex and consists of two columns: Specialization_id and Specialty_id(which is foreign key of Specialty table).
I am going to make insert query by creating a new SPECIALIZATION of an existing specialty.
I have some specializations in my table already, primary key for one specialty with id = 1 looks like (1,1) (2,1), with id = 2 looks like (1,2) (2,2).
Now I am going to add a new Specialization to Specialization table, but this Specialization should reference to existing Specialty.
My idea is
INSERT INTO Specialization ( Specialization_name, Specialization_id, Specialty_id )
VALUES( 'Network technologies','(SELECT Max(Specialization_id) FROM Specialization WHERE Specialty_id = '2')+1', '2');
I've tried with '' clauses and without it, still, I am getting errors.
What should I do here?
In a database like MySQL or ORACLE you should not programatically increment the primary key. Instead you should set the field to AUTOINCREMENT when you design the database.
That would change your INSERT statement to:
INSERT INTO Specialization (Specialization_name, Specialty_id)
VALUES('Network technologies', '2')
which is not only much easier, it is safer.
edited to add: Are you sure Specialty_id is a string? I would think it would be some kind of number.
Your main error is the quotes, since your subquery is quoted it will get processed as a string and not a query.
Also, you don't need to use a subquery if you don't have a main query:
INSERT INTO Specialization ( Specialization_name, Specialization_id, Specialty_id )
SELECT 'Network technologies' As a, Max(Specialization_id)+1 As b, 2 As c
FROM Specialization WHERE Specialty_id = 2
However, like dstudeba said, relying on autonumbers for creating new IDs is probably smarter.

Insert query failing with a Syntax error while trying to run it

Movie Table has 4 Attributes: movie_id, moive_name, desc, genre_id
movie_id (autoNumber) PK
moive_name(short Text)
desc(long Text)
genre_id(number) FK
This is the query I am trying to run
INSERT INTO Movie (moive_name,description,genre_id)
VALUES('Rise','dfdsfsa','1')
I know moive_name is miss spelled but its like that in the db aswell will fix it later.
I am still getting a systax error
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] Syntax error in INSERT INTO statement.
I am sure the table is called Movie. I left out the movie_id field since I want it to auto fill with the next number as its autoNumber. Do you guys maybe know what I am doing wrong?
In your table have four values , but you are trying to insert with three values.
It won't work in oracle.Create Movie_id as a primary key without auto increment and create sequence for your movie id
CREATE SEQUENCE movie_id
MINVALUE 1
START WITH 1
INCREMENT BY 1
CACHE 10
and try this insert statement
INSERT INTO Movie (movie_id,moive_name,description,genre_id)
VALUES(movie_id.nextval,'Rise','dfdsfsa','1')
i think you are trying to insert a string in number '1' should be like 1
INSERT INTO Movie (moive_name,description,genre_id)
VALUES('Rise','dfdsfsa',1)
Hi Tristan,Provide genre_id without single codes as it is a numeric value. Not sure how you are generating movie_id, if it is a sequence number, provide the number
INSERT INTO Movie (movie_id,moive_name,description,genre_id)
VALUES (your_movie_id,'Rise','dfdsfsa',1)

Adding Row in existing table (SQL Server 2005)

I want to add another row in my existing table and I'm a bit hesitant if I'm doing the right thing because it might skew the database. I have my script below and would like to hear your thoughts about it.
I want to add another row for 'Jane' in the table, which will be 'SKATING" in the ACT column.
Table: [Emp_table].[ACT].[LIST_EMP]
My script is:
INSERT INTO [Emp_table].[ACT].[LIST_EMP]
([ENTITY],[TYPE],[EMP_COD],[DATE],[LINE_NO],[ACT],[NAME])
VALUES
('REG','EMP','45233','2016-06-20 00:00:00:00','2','SKATING','JANE')
Will this do the trick?
Your statement looks ok. If the database has a problem with it (for example, due to a foreign key constraint violation), it will reject the statement.
If any of the fields in your table are numeric (and not varchar or char), just remove the quotes around the corresponding field. For example, if emp_cod and line_no are int, insert the following values instead:
('REG','EMP',45233,'2016-06-20 00:00:00:00',2,'SKATING','JANE')
Inserting records into a database has always been the most common reason why I've lost a lot of my hairs on my head!
SQL is great when it comes to SELECT or even UPDATEs but when it comes to INSERTs it's like someone from another planet came into the SQL standards commitee and managed to get their way of doing it implemented into the final SQL standard!
If your table does not have an automatic primary key that automatically gets generated on every insert, then you have to code it yourself to manage avoiding duplicates.
Start by writing a normal SELECT to see if the record(s) you're going to add don't already exist. But as Robert implied, your table may not have a primary key because it looks like a LOG table to me. So insert away!
If it does require to have a unique record everytime, then I strongly suggest you create a primary key for the table, either an auto generated one or a combination of your existing columns.
Assuming the first five combined columns make a unique key, this select will determine if your data you're inserting does not already exist...
SELECT COUNT(*) AS FoundRec FROM [Emp_table].[ACT].[LIST_EMP]
WHERE [ENTITY] = wsEntity AND [TYPE] = wsType AND [EMP_COD] = wsEmpCod AND [DATE] = wsDate AND [LINE_NO] = wsLineno
The wsXXX declarations, you will have to replace them with direct values or have them DECLAREd earlier in your script.
If you ran this alone and recieved a value of 1 or more, then the data exists already in your table, at least those 5 first columns. A true duplicate test will require you to test EVERY column in your table, but it should give you an idea.
In the INSERT, to do it all as one statement, you can do this ...
INSERT INTO [Emp_table].[ACT].[LIST_EMP]
([ENTITY],[TYPE],[EMP_COD],[DATE],[LINE_NO],[ACT],[NAME])
VALUES
('REG','EMP','45233','2016-06-20 00:00:00:00','2','SKATING','JANE')
WHERE (SELECT COUNT(*) AS FoundRec FROM [Emp_table].[ACT].[LIST_EMP]
WHERE [ENTITY] = wsEntity AND [TYPE] = wsType AND
[EMP_COD] = wsEmpCod AND [DATE] = wsDate AND
[LINE_NO] = wsLineno) = 0
Just replace the wsXXX variables with the values you want to insert.
I hope that made sense.

I want to show how many of the alumni attended the social event

I want an output to show how many alumni attended the event
I got Event Table
CREATE TABLE EVENT
(EVENTID INTEGER CONSTRAINT EVENT_ID_PK PRIMARY KEY,
EDATEANDTIME VARCHAR2(20),
EVENUE VARCHAR2(30),
EAUDIENCE VARCHAR2(30),
EATTENDED VARCHAR2(30),
EVENT_ALUMNI INTEGER,
CONSTRAINT EVENT_ALUMNI_FK FOREIGN KEY (EVENT_ALUMNI) REFERENCES
ALUMNI(ALUMNIID));
Here is what I inserted in Event
INSERT INTO EVENT VALUES(25993, 'Jan 14, 2015', 'Concorde Hall', 'Tobias, Tucker, Felix, Nicole, Desiree, Taylor, Frant, Ifeoma, Forrest, Stewart, Cole, Arthur, Thomas, Bo, Lucian',
'Tobias, Tucker, Felix, Nicole, Desiree, Taylor, Frant, Ifeoma, Forrest, Stewart, Cole, Arthur, Thomas, Bo',17337);
INSERT INTO EVENT VALUES(23823, 'July 18 2015', 'Rochester Hotel', 'Joan, Thalia, Haleeda', 'Joan, Haleeda'
,19927);
And I have a View Statement to view how many attended
CREATE VIEW VIEWH AS SELECT ETYPE, EDATEANDTIME, COUNT (*) EATTENDED FROM EVENT
WHERE EDATEANDTIME LIKE '%2015%' AND ETYPE = 'Social'
GROUP BY ETYPE, EDATEANDTIME, EATTENDED;
Here is where I got problem. When i run the query, the output is I got only one who attended the event instead of like 10 or 15
I want to know where i went wrong.
There are several potential problems with your setup, I mentioned a couple in a Comment to your question.
Regarding the count specifically: your first problem is you have EATTENDED in the GROUP BY clause. Why? This almost surely means that each group is exactly one row.
Then your next problem is counting tokens out of a comma-separated string. One way is using regexp_count() as TheGameiswar has shown. (err... his/her solution has disappeared? anyway, I was saying...)
Another is to use length() and translate():
select ... , 1 + length(EATTENDED) - length(translate(EATTENDED, ',', '') as ATT_CNT ...
A couple of notes about this:
The length difference, just like regexp_count(), counts commas in the string. You add one to count tokens (you don't care how many commas there are, you care how many names are separated by commas). translate() works faster than regexp_count() (all regexp functions are very powerful, but slower, so they should be used only when they are really needed, IF performance is important); length doesn't add much overhead since in Oracle the length of VARCHAR2 is always calculated and stored as part of the internal representation of a string.
I gave a different alias to the resulting column; in your original query you use the same name, EATTENDED, for a column in your base table and as an alias for this numeric column in your view. You can do it, it's legal, but it is almost certain to cause problems in the future.
It is because COUNT gives number of "rows" in the result and not number of "values in column".
To give you a simple example
example1_table:
col1
--------
a
b
c
SELECT COUNT(col1) FROM example1_table; // The result is 3, as there are three rows
example2_table:
col1
--------
a,b,c
SELECT COUNT(col1) FROM example1_table; // The result is 1, as there is only one row (it is not about number of values in it)
Note:
As stated by #mathguy you could have used a better Database structure.
Instead of using only one table EVENT create two tables let they be: table1 table2 so you could avoid redundancy.
CREATE TABLE table1
(EVENTID INTEGER CONSTRAINT EVENT_ID_PK PRIMARY KEY,
EDATEANDTIME VARCHAR2(20),
EVENUE VARCHAR2(30),
EVENT_ALUMNI INTEGER,
CONSTRAINT tab1_FK FOREIGN KEY (EVENT_ALUMNI) REFERENCES
ALUMNI(ALUMNIID));
CREATE TABLE table2
(
EAUDIENCE VARCHAR2(30),
EATTENDED VARCHAR2(30),
tab2ID INTEGER
CONSTRAINT tab2_FK FOREIGN KEY (tab2ID) REFERENCES
tab1(EVENT_ALUMNI));
If you don't want to make any changes in your table, assuming there is always a comma present between two attendees names you could try:
CREATE VIEW VIEWH AS SELECT ETYPE, EDATEANDTIME, regexp_count(EATTENDED,',')+1 FROM EVENT WHERE EDATEANDTIME LIKE '%2015%' AND ETYPE = 'Social' GROUP BY ETYPE, EDATEANDTIME;

What the best way to self-document "codes" in a SQL based application?

Q: Is there any way to implement self-documenting enumerations in "standard SQL"?
EXAMPLE:
Column: PlayMode
Legal values: 0=Quiet, 1=League Practice, 2=League Play, 3=Open Play, 4=Cross Play
What I've always done is just define the field as "char(1)" or "int", and define the mnemonic ("league practice") as a comment in the code.
Any BETTER suggestions?
I'd definitely prefer using standard SQL, so database type (mySql, MSSQL, Oracle, etc) should't matter. I'd also prefer using any application language (C, C#, Java, etc), so programming language shouldn't matter, either.
Thank you VERY much in advance!
PS:
It's my understanding that using a second table - to map a code to a description, for example "table playmodes (char(1) id, varchar(10) name)" - is very expensive. Is this necessarily correct?
The normal way is to use a static lookup table, sometimes called a "domain table" (because its purpose is to restrict the domain of a column variable.)
It's up to you to keep the underlying values of any enums or the like in sync with the values in the database (you might write a code generator to generates the enum from the domain table that gets invoked when the something in the domain table gets changed.)
Here's an example:
--
-- the domain table
--
create table dbo.play_mode
(
id int not null primary key clustered ,
description varchar(32) not null unique nonclustered ,
)
insert dbo.play_mode values ( 0 , "Quiet" )
insert dbo.play_mode values ( 1 , "LeaguePractice" )
insert dbo.play_mode values ( 2 , "LeaguePlay" )
insert dbo.play_mode values ( 3 , "OpenPlay" )
insert dbo.play_mode values ( 4 , "CrossPlay" )
--
-- A table referencing the domain table. The column playmode_id is constrained to
-- on of the values contained in the domain table playmode.
--
create table dbo.game
(
id int not null primary key clustered ,
team1_id int not null foreign key references dbo.team( id ) ,
team2_id int not null foreign key references dbo.team( id ) ,
playmode_id int not null foreign key references dbo.play_mode( id ) ,
)
go
Some people for reasons of "economy" might suggest using a single catch-all table for all such code, but in my experience, that ultimately leads to confusion. Best practice is a single small table for each set of discrete values.
add a foreign key to "codes" table.
the codes table would have the PK be the code value, add a string description column where you enter in the description of the value.
table: PlayModes
Columns: PlayMode number --primary key
Description string
I can't see this as being very expensive, databases are based on joining tables like this.
That information should be in database somewhere and not on comments.
So, you should have a table containing that codes and prolly a FK on your table to it.
I agree with #Nicholas Carey (+1): Static data table with two columns, say “Key” or “ID” and “Description”, with foreign key constraints on all tables using the codes. Often the ID columns are simple surrogate keys (1, 2, 3, etc., with no significance attached to the value), but when reasonable I go a step further and use “special” codes. Following are a few examples.
If the values are a sequence (say, Ordered, Paid, Processed, Shipped), I might use 1, 2, 3, 4, to indicate sequence. This can make things easier if you want to find all “up through” a give stages, such as all orders that have not yet been shipped (ID < 4). If you are into planning ahead, make them 10, 20, 30, 40; this will allow you to add values “in between” existing values, if/when new codes or statuses come along. (Yes, you cannot and should not try to anticipate everything and anything that might have to be done some day, but a bit of pre-planning like this can make some changes that much simpler.)
Keys/Ids are often integers (1 byte, 2 byte, 4 byte, whatever). There’s little cost to make them character values (1 char, 2 char, 3, char, 4 char). That’s character, not variable character. Done this way, you can have mnemonics on your codes, such as
O, P, R, S
Or, Pd, Pr, Sh
Ordr, Paid, Proc, Ship
…or whatever floats your boat. Done this way, I have found that it can save a lot of time when analyzing or debugging. You still want the lookup table, for relational integrity as well as a reminder for the more obscure codes.