insert date difference in last column - sql

I want to insert date difference of 4th and 5th column in the 6th column but it is giving me error saying column not allowed.
insert into leave25 vALUES (4, 4, 'SICK', TO_DATE('22-AUG-14','DD-MON-YY'), TO_DATE('22-SEP-14','DD-MON-YY'), startdate-enddate)\\

Always specify the column names explicitly in your INSERT statements. It is safer that way.
If you want to avoid writing the dates again, you could select the values from a subquery.
INSERT INTO leave25
(col1,
col2,
col3,
startdate,
enddate,
days)
SELECT t.*,
startdate - enddate
FROM (SELECT 4,
4,
'SICK',
to_date('22-AUG-14', 'DD-MON-YY') as startdate,
to_date('22-SEP-14', 'DD-MON-YY') as enddate
FROM dual) t;
Furthermore, I agree with Aleksej, it is better to have this difference stored as a virtual column rather than a column itself.

You can not do it this way, you need to esplicitly use the values you want to insert:
INSERT INTO leave25
VALUES (
4,
4,
'SICK',
TO_DATE('22-AUG-14', 'DD-MON-YY'),
TO_DATE('22-SEP-14', 'DD-MON-YY'),
TO_DATE('22-SEP-14', 'DD-MON-YY') - TO_DATE('22-AUG-14', 'DD-MON-YY')
Besides, if this column always contains that difference, are you sure you need to store this redundant information?
A different approach could be by using a trigger to populate that column without explicitly giving it a value, but this depends on your environment and your needs.

Use a virtual column:
CREATE TABLE Leave25(
EMPLOYEEID INTEGER
CONSTRAINT LEAVE25__EMPID__FK REFERENCES Employee24,
LEAVEID INTEGER
CONSTRAINT LEAVE25__LEAVEID__PK PRIMARY KEY,
LEAVETYPE VARCHAR2(20)
CONSTRAINT LEAVE25__LEAVETYPE__NN NOT NULL
CONSTRAINT LEAVE25__LEAVETYPE__CHK CHECK (
LEAVETYPE IN 'EARNED', 'SICK'
),
STARTDATE DATE
CONSTRAINT LEAVE25__STARTDATE__NN NOT NULL,
ENDDATE DATE
CONSTRAINT LEAVE25__ENDDATE__NN NOT NULL,
DURATION NUMBER
GENERATED ALWAYS AS ( ENDDATE - STARTDATE ) VIRTUAL
);
And create a sequence to manage the primary key:
CREATE SEQUENCE LEAVE25__LEAVEID__SEQ;
Then you can do:
INSERT INTO leave25 (
EMPLOYEEID, LEAVEID, LEAVETYPE, STARTDATE, ENDDATE
) VALUES (
4, LEAVE25__LEAVEID__SEQ.NEXTVAL, 'SICK', DATE '2014-08-22', DATE '2014-09-22'
)

Related

Insert statement Oracle

Here is my table
create table reservations (
ResID int NOT NULL,
GuestID int,
HotelID int,
Check_in DATE,
Check_out DATE,
RoomType varchar2(15),
Price Dec(8,2),
PRIMARY KEY (ResID),
CONSTRAINT FK_GuestIDX FOREIGN KEY(GuestID) REFERENCES Guests(GuestID),
CONSTRAINT FK_HotelID FOREIGN KEY(HotelID) REFERENCES Hotel(HotelID)
);
Table was created with no problems. Now Im trying to populate the table
Here is my insert statement
insert into reservations (1, 1, 2, '17-DEC-2018', '21-DEC-2018', 'Suite', 87.03);
and here is the error that I'm getting
ORA-00928: missing SELECT keyword
What could be the cause for this?
Or missing values:
insert into reservations
values (1, 1, 2, '17-DEC-2018', '21-DEC-2018', 'Suite', 87.03);
That said, I would recommend writing this as:
insert into reservations (ResID, GuestID, HotelID, Check_in, Check_out DATE, RoomType, Price)
values (1, 1, 2, DATE '2018-12-17', DATE '2018-12-21', 'Suite', 87.03);
Note:
List the columns after the insert. This can really prevent hard-to-debug errors.
This uses the DATE keyword to introduce a date constant.
You can also write this using SELECT:
insert into reservations (ResID, GuestID, HotelID, Check_in, Check_out DATE, RoomType, Price)
select 1, 1, 2, DATE '2018-12-17', DATE '2018-12-21', 'Suite', 87.03
from dual;

Reference table from subquery in Oracle

I have simplified my tables but essentially I have a table of accounts that have a cycle_no and end date. This end date is always set to the first of the month but I need to get the real end date by looking in the calendar details table. The real end date is the next date for this cycle_no.
To create the simplified tables and enter a few rows of data:
CREATE TABLE DATA_OWNER.ACCOUNT
(
ACCNO NUMBER(4),
CYCLE_NO NUMBER(4),
ENDDATE DATE
);
CREATE TABLE DATA_OWNER.CALENDAR_DETAILS
(
CALENDAR_DT DATE,
BILL_CYCL_NO NUMBER(4)
);
INSERT INTO calendar_Details
VALUES
('18/DEC/2017',
17);
INSERT INTO calendar_Details
VALUES
('23/DEC/2017',
20);
INSERT INTO calendar_Details
VALUES
('18/JAN/2018',
17);
INSERT INTO calendar_Details
VALUES
('23/JAN/2018',
20);
INSERT INTO calendar_Details
VALUES
('20/FEB/2018',
17);
INSERT INTO calendar_Details
VALUES
('21/FEB/2018',
20);
INSERT INTO account
VALUES
(1, 17, '01/DEC/2107');
INSERT INTO account
VALUES
(2, 20, '01/DEC/2107');
If we run this query though we get "ACC". "ENDDATE": invalid identifier:
SELECT accno, cycle_no, enddate, actual_date
FROM account acc
JOIN
(
SELECT MIN(calendar_dt) actual_date
FROM calendar_details cal
WHERE calendar_dt > acc.enddate
)
ON acc.cycle_no = cal.bill_cycl_no;
Can anyone give us some pointers on the best way to achieve this please?
You cannot refer to outer table references in a subquery in the FROM. Just use a correlated subquery:
SELECT accno, cycle_no, enddate,
(SELECT MIN(cal.calendar_dt) as actual_date
FROM calendar_details cal
WHERE cal.calendar_dt > acc.enddate AND acc.cycle_no = cal.bill_cycl_no
) as actual_date
FROM account acc;

SQL Server : inserting date returning wrong value

When I try to insert information from another table, it is returning '1900-01-01' from a date column when it should be empty. On the import table the datatype is varchar and on the table I want to insert the information into it is a date datatype. There are some empty values in the EndDate column that should be inserted as empty but it is returning '1900-01-01'
Insert into tblServiceHistory (PersonID, PositionID, CommitteeID,StartDate, EndDate)
Select distinct
PersonID, PositionID, CommitteeID, StartDate, EndDate
From
tblCommitteeOfficers_IMPORT
Where
PersonID is not null
And StartDate is not null
And PositionID is not null
And CommitteeID is not null
Blank strings converted to dates turn in to '1900-01-01'.
e.g. select convert(date,'') returns '1900-01-01'.
You can use nullif() to turn empty strings into null values in your select.
Try this:
Insert into tblServiceHistory (PersonID, PositionID, CommitteeID,StartDate, EndDate)
Select distinct PersonID, PositionID, CommitteeID, nullif(StartDate,''), nullif(EndDate,'')
From tblCommitteeOfficers_IMPORT
Where PersonID is not null
AND nullif(StartDate,'') is not null
AND PositionID is not null
AND CommitteeID is not null

Why SQL Server Optimizer do not use CHECK constraint definitions to find which table contains the rows?

I use SQL Server 2012 and I have a large table and I divided my table in some tables like below :
Create Table A2013
(
Id int identity(1,1),
CountA int ,
Name varchar(50),
ADate DATETIME NULL
CHECK (DATEPART(yy, ADate) = 2013)
)
Create Table A2014
(
Id int identity(1,1),
CountA int ,
Name varchar(50),
ADate DATETIME NULL
CHECK (DATEPART(yy, ADate) = 2014)
)
Insert Into A2013 Values ( 102 , 'A','20131011' )
Insert Into A2013 Values (15 , 'B' ,'20130211' )
Insert Into A2013 Values ( 54, 'C' ,'20131211' )
Insert Into A2013 Values ( 54, 'D' ,'20130611' )
Insert Into A2013 Values ( 95, 'E' ,'20130711' )
Insert Into A2013 Values (8754 , 'F' ,'20130310' )
Insert Into A2014 Values ( 102 , 'A','20141011' )
Insert Into A2014 Values (15 , 'B' ,'20140911' )
Insert Into A2014 Values ( 54, 'C' ,'20140711' )
Insert Into A2014 Values ( 54, 'D' ,'20141007' )
Insert Into A2014 Values ( 95, 'E' ,'20140411' )
Insert Into A2014 Values (8754 , 'F' ,'20140611' )
I created a partition view like below:
Create View A
As
Select * From A2013
Union
Select * From A2014
I hope SQL Optimizer use a good plan and use my CHECK constraint definitions to determine which member table contains the rows but it scan two table when run this query :
Select * From A Where A.ADate = '20140611'
I expected that SQL Optimiser do not use table A2013?!?
The CHECK CONSTRAINT expression must be sargable in order for the optimizer to eliminate the unneeded tables in the execution plan. The constraints below avoid applying a function to the column and are sargable:
CREATE TABLE dbo.A2013
(
Id int IDENTITY(1, 1)
, CountA int
, Name varchar(50)
, ADate datetime NULL
CONSTRAINT CK_A2013_ADate
CHECK ( ADate >= '20130101'
AND ADate < '20140101' )
);
CREATE TABLE dbo.A2014
(
Id int IDENTITY(1, 1)
, CountA int
, Name varchar(50)
, ADate datetime NULL
CONSTRAINT CK_A2014_ADate
CHECK ( ADate >= '20140101'
AND ADate < '20150101' )
);
The issue is not whether the expression is sargable. As far as I know, the term "sargable" applies to the use of indexes in queries. The question is whether SQL Server recognizes the where clause as matching the check constraint.
The check constraint you have is:
CHECK (DATEPART(yy, ADate) = 2014)
The where clause is:
Where A.ADate = '20140611'
The problem is that the second is not recognized as a subset of the first. You could fix this by adding redundancy:
Where A.ADate = '20140611' and DATEPART(yy, A.ADate) = 2014
Or, you could fix this by using ranges -- but be careful about data types, because data type conversion can definitely confuse the optimizer. I think the following will work:
CHECK ADate BETWEEN '2014-01-01' and '2014-12-31'
WHERE A.ADate = '2014-06-11'
(The hyphens are optional and can be dropped.)
The documentation (as far as I can tell) is not really explicit about the cause:
The SQL Server query optimizer recognizes that the search condition in
this SELECT statement references only rows in the May1998Sales and
Jun1998Sales tables. Therefore, it limits its search to those tables.
. . .
CHECK constraints are not needed for the partitioned view to return
the correct results. However, if the CHECK constraints have not been
defined, the query optimizer must search all the tables instead of
only those that cover the search condition on the partitioning column.
Without the CHECK constraints, the view operates like any other view
with UNION ALL. The query optimizer cannot make any assumptions about
the values stored in different tables and it cannot skip searching the
tables that participate in the view definition.

Constraining Child Record Based on Parent Record

In a timesheets data model, suppose I have the following parent table:
CREATE TABLE EmployeeInRole (
employeeInRoleId PRIMARY KEY,
employeeId,
roleId,
rate,
effectiveFrom DATE, --from when can this employee assume this role
effectiveTo DATE
);
and the following child table:
CREATE TABLE TimesheetEntry (
startTime DATETIME,
endTime DATETIME,
employeeInRoleId,
CONSTRAINT fk FOREIGN KEY (employeeInRoleId) REFERENCES EmployeeInRole (employeeInRoleId)
);
When I insert into TimesheetEntry, I'd like to make sure that time period falls within the boundaries of the parent record's effectiveFrom/To.
Is it possible to build this constraint into the DDL without use of a trigger, or do I have to maintain this constraint via a trigger or at the application level?
(Here is some info about Oracle only)
It's not possible in Oracle with clear DDL but you can do something like this:
create table t1 (id number primary key, date_from date, date_to date);
create table t2 (id number primary key, date_from date, date_to date, parent_id number references t1(id));
create view v as
select t2.* from t2
where exists (select 1 from t1 where t1.id = t2.parent_id
and t2.date_from between t1.date_from and t1.date_to
and t2.date_to between t1.date_from and t1.date_to)
with check option constraint chk_v;
insert into t1 values (1, sysdate - 5, sysdate); -- OK
insert into v values (1, sysdate - 4, sysdate - 3, 1); -- OK
insert into v values (1, sysdate - 6, sysdate - 3, 1); -- ERROR (WITH CHECK OPTION where-clause violation)
V is updatable view created with CHECK OPTION
"Is it possible to build this constraint into the DDL without use of a trigger,"
It is possible in some RDBMS systems, but it is not possible in SQL.