Inserting into a table with datetime column - sql

I'm trying to create and use a table with a timestamp field. I tried creating it like this.
CREATE TABLE testdb(timestamp DATETIME, value INT NOT NULL)
I tried inserting into the table with these commands, but they both fail.
INSERT INTO testdb(TIMESTAMP_NOW, 3)
INSERT INTO testdb(GETDATE(), 3)
How do I create a table with a field for a timestamp, and how do I insert into that table?

The correct syntax would have a column list and values:
INSERT INTO testdb (timestamp, value)
VALUES (GETDATE(), 3);

Related

sql unique constraint with time window

I have a table where records have a (begin, end) time window of existence (for things like employement duration, birth and death, rent duration, ...)
begin IS NULL or end IS NULL if there is no bound.
CREATE TABLE mytable(
id int primary key,
value int, --UNIQUE at any point in time
begin datetime NULL,
end datetime NULL
);
I want column value to be unique at any point in time.
INSERT INTO mytable VALUES(1, 1, '2021-07-23', '2021-07-24'),(2, 1, '2021-07-25', NULL);
Is OK
Whereas
INSERT INTO mytable VALUES(1, 1, '2021-07-23', '2021-07-30'),(2, 1, '2021-07-25', NULL);
Is not OK, because both records have value=1 and overlapping time windows.
Is there a way to enforce such a constraint in SQL ?
You can't do this on the table, no, as there's nothing to make UNIQUE on.
What you could do, however, is use a VIEW to enforce it.
Firstly, let's create your table. I assume the columns datetime, should actually be begin and end; I recommend against these names as they are reserved keywords. As such I am calling them DateBegin and DateEnd. I am also assuming that they are date only (no time portion) values and so define them as a date not a datetime:
CREATE TABLE dbo.mytable(ID int primary key,
Value int,
[BeginDate] date NULL,
[EndEnd] date NULL);
And we'll INSERT your first 2 rows, as they are "ok":
INSERT INTO dbo.mytable (ID, Value, BeginDate, EndDate)
VALUES(1, 1, '20210723', '20210724'),
(2, 1, '20210725', NULL);
Now we need to make a VIEW, but we need one row per date. As such you'll want to create a Calendar Table. I'm not going to cover how to create one here, but there are literally 100's of articles, such as there on SQL Server Central: Bones of SQL - The Calendar Table, Calendar Tables in T-SQL.
Once you have your Calendar table, you can create the VIEW below, which JOINs the data in your table to the calendar table. We're going to make it so that the VIEW just returns the columns value and the date. WE're also going to schemabind it; this means we'll be able to add an UNIQUE INDEX to it:
CREATE VIEW dbo.MyView
WITH SCHEMABINDING
AS
SELECT MT.[Value],
CT.CalendarDate
FROM dbo.MyTable MT
JOIN dbo.CalendarTable CT ON MT.BeginDate <= CT.CalendarDate --I assume, despite your schema, MT.BeginDate can't be NULL
AND (MT.EndDate >= CT.CalendarDate OR MT.EndDate IS NULL);
Now we have a VIEW that has a row for each date, and for each value. This means we can now create our UNIQUE INDEX:
CREATE UNIQUE CLUSTERED INDEX MyIndex ON dbo.MyView ([Value], CalendarDate);
Now if we try to INSERT a row that is on the same date and value, we'll get an error:
INSERT INTO dbo.MyTable (ID, Value, BeginDate, EndDate)
VALUES(3, 1, '20210720', '20210723');
Cannot insert duplicate key row in object 'dbo.MyView' with unique index 'MyIndex'. The duplicate key value is (1, 2021-07-23).

Inserting into table

I have this table on an Oracle server with this structure:
Create table temp
(
input number(10),
str varchar(24),
constraint L_PK PRIMARY KEY(input, str)
)
I made one alteration on it:
alter table temp add userID number(10);
Now I am trying to do an insert:
insert into temp values (9, 7, 'sure.');
But I am getting a error saying:
ORA-01722: Invalid Number
Any ideas? I'm pretty sure its coming from the 'sure' but I can't say for sure.
Specify the column-names when you are inserting so the appropriate data is inserted into the columns.
insert into temp (input, userid, str)
values (9, 7, 'sure.');
So you created a table with two columns:
Create table temp(
input number(10),
str varchar(24),
constraint L_PK PRIMARY KEY(input,str),
Made one alteration to it:
alter table temp add userID number(10);
Which leaves you with a table with columns input, str, and userID in that order. You then try to insert
insert into temp values (9, 7, 'sure.');
which tries to insert 9 into input (fine), 7 into str (not fine), and sure into userID (again, not fine).
You need to either use the values in the proper order to match the column order:
insert into temp values (9, 'sure', 7);
or (much better and safer) specify the columns first, and then assign the values to match:
insert into temp (input, userID, str) values (7, 9, 'sure');
In your case:
insert into temp values (9, 7, 'sure.');
It means:
INSERT INTO temp (input, str, userId)
VALUES (9, 7, 'sure.');
As 'sure.' does not a number type, Oracle server certainly gets error.
If you don't change the insert order,you should change the alteration SQL:
alter table temp add userID number(10) after str;
Yes,'after str' is appended.
Or you could change the insert order like this:insert into temp values (9, 'sure', 7);
Whatever you must remember that column should match with the value,especially in datatype.
You added userID at the end of the table. Try
insert into temp values (9, 'sure.', 7);
After adding column,it is added at the end of the table
insert into temp values (9, 'sure.',7);
output:
input str userID
9 sure. 7

Specify "NEXT VALUE" for INSERT statement using identity column in SQL Server

Consider the following table and SQL from Microsoft's INSERT documentation that deals with IDENTITY columns:
CREATE TABLE dbo.T1 (column_1 int IDENTITY, column_2 VARCHAR(30));
GO
INSERT T1 (column_2) VALUES ('Row #2');
The INSERT statement does not specify column_1 as a column of the table, and SQL Server auto-populates the next value for that identity column. This is the normal way identity columns are handled.
How can I have the same behavior, while also specifying the column name?
For example, I'm looking for something like:
INSERT INTO T1 (column_1, column_2)
VALUES (NEXT VALUE, 'Row #3');
GO
I don't believe NEXT VALUE works here, but is there something that does work? Is there a key token or function that will indicate that the identity column should be used?
Note: the reason I ask is that the framework I'm using requires all columns to be specified in the column list.
If you are on SQL Server 2012 and later, you can use sequence. But you must remove the IDENTITY property from Column1 first. This can only be done by copy-and-rename a new table.
CREATE SEQUENCE Column1_Sequence
AS int
START WITH 0;
CREATE TABLE T1
(
Column1 int DEFAULT (NEXT VALUE FOR Column1_Sequence) PRIMARY KEY
, Column2 nvarchar(30)
)
After that, you can insert data into the table in 2 ways:
INSERT INTO T1 (Column1, Column2)
SELECT NEXT VALUE FOR Column1_Sequence
, 'Row #2'
INSERT INTO T1 (Column2)
SELECT 'Hello world'
Can you set the identity insert on before inserting and then set the identity insert off
You cannot set value for identity column unless you set identity_insert on for this table (one at time). Some examples:
create table #tmp (id int identity(1,1), name varchar(10))
insert #tmp (id,name) values (2,'test')
--error Cannot insert explicit value for identity column in table '#tmp
set identity_insert #tmp on --for one table in DB
insert #tmp (id,name) values (2,'qwas')
select * from #tmp
set identity_insert #tmp off -- good practice
--works
--see current identity value
SELECT IDENT_CURRENT ('#tmp') AS Current_Identity;
--Reset identity value
DBCC CHECKIDENT (#tmp, RESEED, 999)
--next insert will be 1000
Of course, if you reset next identity to a value which conflicts with PK (common usage of identity) you will have Violation of PRIMARY KEY constraint error
I am pretty sure there is no way to do that with SQL Server. Two workarounds that I can think of:
Fix the library if possible.
If the library supports it, you can create a view and INSERT into that instead. For example:
CREATE TABLE MyTable
(
ID INT IDENTITY(1, 1),
SomeColumn VARCHAR(100)
)
GO
CREATE VIEW MyTableView
AS
SELECT SomeColumn
FROM MyTable
GO
INSERT INTO MyTableView (SomeColumn) VALUES ('Test')

When we create a table how to tall SQLITE to set default value of datetime to `now`?

We have something like:
CREATE TABLE IF NOT EXISTS files
(encoded_url varchar(65) UNIQUE NOT NULL primary key, modified DATETIME NOT NULL);
We want each time a new record is created to fill its modified field with now time automatically. Can we tall SQLite that it has to do such thing when we create a table or we should always insert nowwhen we fill in a row?
You can use default CURRENT_TIMESTAMP in the column specification:
sqlite> create table t (a datetime default CURRENT_TIMESTAMP, b text);
sqlite> insert into t(b) values ('hello');
sqlite> select * from t;
2011-10-16 17:29:54|hello
sqlite> insert into t(b) values ('hello again');
sqlite> select * from t;
2011-10-16 17:29:54|hello
2011-10-16 17:30:04|hello again
There are other date/time options, documented in the column definition part of the create table syntax docs.
CREATE TABLE IF NOT EXISTS files
(encoded_url varchar(65) UNIQUE NOT NULL primary key, modified DEFAULT (datetime('now','localtime')) NOT NULL);

Calculated columns in mysql on INSERT statements

Let's say that I want to have a table that logs the date and the number of columns in some other table (or really any sort of math / string concat etc).
CREATE TABLE `log` (
`id` INTEGER NOT NULL AUTO_INCREMENT ,
`date` DATETIME NOT NULL ,
`count` INTEGER NOT NULL ,
PRIMARY KEY (`id`)
);
Is it possible to have the count column calculated for me whenever I do an insert?
e.g. do something like:
INSERT INTO log (date='foo');
and have count calculated by mysql.
Obviously I could do it myself by doing a query to get the count and inserting it, but this would be better.
Triggers are the best tool for annotating data when a table is changed by insert, update or delete.
To automatically set the date column of a new row in the log with the current date, you'd create a trigger that looked something like this:
create trigger log_date before insert on log
for each row begin
set new.date = current_date()
end;
You definitly have to declare what to insert. This should be possible by using the INSERT ... SELECT statement.
INSERT INTO log (date, count)
SELECT DATE() as date, count(id) as count
from foo;
Which should insert a new row into the log table, containing todays date and the number of rows in the foo table. (Assuming the foo table has an id column.. Use the primary key or another indexed column)
Why don't you use information_schema.TABLES?