Calculated columns in mysql on INSERT statements - sql

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?

Related

PostgreSQL- insert result of query into exisiting table, auto-increment id

I have created an empty table with the following SQL statement. My understanding (based on this tutorial: https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-serial/) was that SERIAL PRIMARY KEY will automatically provide an auto-incremented id for every new row:
CREATE TABLE "shema".my_table
(
id SERIAL PRIMARY KEY,
transaction text NOT NULL,
service_privider text NOT NULL,
customer_id text NOT NULL,
value numeric NOT NULL
)
WITH (
OIDS = FALSE
);
ALTER TABLE "shema".my_table
OWNER to admin;
Now I am querying another tables and would like to save the result of that query into my_table. The result of the query outputs following schema:
transaction
service_provider
customer_id
value
meaning the schema of my_table minus id. when I try to execute:
INSERT into my table
Select {here is the query}
Then I am getting an error that column "id" is of type integer but expression is of type text. I interpret it that the sql query is looking for id column and cannot find it. How can I insert data into my_table without explicitly stating id number but have this id auto-generated for every row?
Always mention the columns you want to INSERT:
INSERT INTO schemaname.my_table("transaction", service_privider, customer_id, value)
SELECT ?, ?, ?, ?;
If you don't, your code will break now or somewhere in the future.
By the way, transaction is a reserved word, try to use a better column name.

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).

sql current date constraint

I need to add a constraint to one table in my database. The table name is Experience. And there is a column named ToDate. Every time the select statement executes like following.
select ToDate from Experience
It should return current date.
So every time select statement executes, the ToDate column get updated with current date.
I know I can do this with some type of sql trigger but is there a way to do it by sql constraint.
like
alter table add constraint...
Any help will be appreciated.
Thanks
You can use a computed column. That's specified like colname as <expression>:
create table t1(id int, dt as getdate());
insert t1 values (1);
select * from t1;
To add contraint ...
create table tbl (id int identity, dt datetime, colval varchar(10))
ALTER TABLE dbo.tbl
ADD CONSTRAINT col_dt_def
DEFAULT GETDATE() FOR dt;
Example of inserting to the table ..
insert into dbo.tbl(colval)
select 'somevalue'
select * from dbo.tbl
The result will be ..
id dt colval
1 2014-08-19 13:31:57.577 somevalue
You cannot use a constraint, because a constraint is basically a rule on what can go in the table, how the table can relate to others, etc. It has no bearing on the data in the table once it goes into the table. Now if I am understanding you correctly, you want to update the ToDate column whenever you select that column. Now you can't use a trigger either as mentioned here and here. They suggest a stored procedure where you would use an update followed by an insert. This is probably my preferred SQL method to go with if you have to use it repeated, which you seem to have to do. Though Andomar's answer is probably better.
Try this link code make help full
http://www.sqlatoms.com/queries/how-to-use-the-getdate-function-in-sql-server-3/
CREATE TABLE ProductOrders
(
OrderId int NOT NULL PRIMARY KEY IDENTITY,
ProductName nvarchar(50) NOT NULL,
OrderDate datetime NOT NULL DEFAULT GETDATE()
)

SQL Server Database unique number generation on any record insertion

I have like 11 columns in my database table and i am inserting data in 10 of them. i want to have a unique number like "1101 and so on" in the 11th column.
Any idea what should i do?? Thanks in advance.
SQL Server 2012 and above you can generate Sequence
Create SEQUENCE RandomSeq
start with 1001
increment by 1
Go
Insert into YourTable(Id,col1...)
Select NEXT VALUE FOR RandomSeq,col1....
or else you can use Identity
Identity(seed,increment)
You can start the seed from 1101 and increment the sequence by 1
Create table YourTable
(
id INT IDENTITY(1101,1),
Col varchar(10)
)
If you want to have that unique number in a different field then you can manipulate that field with primary key and insert that value.
If you want in primary key value, then open the table in design mode, go to 'Identity specification', set 'identity increment' and 'identity seed' as you want.
Alternatively you can use table script like,
CREATE TABLE Persons
(
ID int IDENTITY(12,1) PRIMARY KEY,
FName varchar(255) NOT NULL,
)
here the primary key will start seeding from 12 and seed value will be 1.
If you have your table definition already in place you can alter the column and add Computed column marked as persisted as:
ALTER TABLE tablename drop column column11;
ALTER TABLE tablename add column11 as '11'
+right('000000'+cast(ID as varchar(10)), 2) PERSISTED ;
--You can change the right operator value from 2 to any as per the requirements.
--Also replace ID with the identity column in your table.
create table inc
(
id int identity(1100,1),
somec char
)

Update value on insert into table in SQL Server

I am working with SQL Server - on inserting into a table, I have a unique constraint on a table column id. There is a possibility that when inserting, the value going into the id column is 0. This will cause an error.
Is it possible to update this id to another value during the insert if the id value is 0? This is to prevent the error and to give it a valid value.
Possibly a trigger?
A trigger is one way, but you may want to use a filtered index (CREATE UNIQUE INDEX, not as a table constraint) to ignore zero value. This way, you don't have to worry about what value to put there
Alternatively, if you want to populate it from another column, you can have a computed column with a unique constraint.
ALTER TABLE whatever
ADD ComputedUniqueCol = CASE WHEN Id = 0 THEN OtherCol ELSE Id END
If that's your primary key you can specify it as IDENTITY. Then it should generate a value for itself based on seed and increment (the default is seed=1 and default=1) so you don't have to worry about it.
CREATE TABLE MyTable
(
ID int PRIMARY KEY IDENTITY,
...
)
create an "instead of" trigger and check for the value on the ID.
CREATE trigger checkID
on YOUR_TABLE
instead of insert
as
begin
declare #id int
select #id=id from inserted
if (#id==0) begin
--DO YOUR LOGIC HERE AND THEN INSERT
end else begin
insert into DESTINATION_TABLE (VALUES)
SELECT VALUES FROM INSERTED
end
end