Sqlite3: How to check date input - sqlite

I created a table tb with the following schema:
CREATE TABLE tb (name TEXT, dt TEXT DEFAULT (date('now', 'localtime')));
Then a wrong date was inserted into tb on purpose:
INSERT INTO tb(name, dt) VALUES("somebody","2015-99-99");
It worked without any warning, and with SELECT * FROM tb I got:
somebody|2015-99-99
The date() function showed that the input was wrong, (SELECT DATE(dt) FROM tb returned nothing), but at the time of inputting we did not know the error.
Is it possible for sqlite3 to check if a timestamp input is correct or not?
(Sqlite version: 3.9.1)

To check a field, use a CHECK constraint:
CREATE TABLE tb (
name TEXT,
dt TEXT DEFAULT (date('now', 'localtime')) CHECK (date(dt) IS NOT NULL)
);

Related

Modify format of sqllite select columns

I am pretty new to SqlLite db. I have the following table along with its data. I want to modify the columns data which appears as output.
CREATE TABLE students (studentId TEXT, firstName TEXT, studentNo TEXT);
INSERT INTO students VALUES ("6b975012-ec43-496e-b1df-44a214437287" ,"Virat" ,"530642685”);
The following select query should return
SELECT studentNo from students;
XXXXX2685
I have tried using built in functions available with SqlLite without any luck.
SELECT REPLACE(studentNo, '', 'X') as Student_SSN from students;
Could anyone please let me know how to achieve this.
thanks
select studentNo,
format('%.*c', length(studentNo)-4, 'X') || substr(studentNo,-4,4) as student_SSN
from students;
Result:
studentNo|student_SSN|
---------+-----------+
530642685|XXXXX2685 |
If the number of 'X' is not important, use a string literal:
select studentNo,
'XXXXX' || substr(studentNo,-4,4) as student_SSN
from students;

FIREDAC-UTF8 encoding is not supported when reading FTS table

When in DELPHI XE3 with Firedac we create a table table0 and insert text in UTF8 encoding all is OK.
CREATE TABLE table0 (mytext Ntext,publishdate date);
INSERT INTO table0 (mytext,publishdate) VALUES ('привет','1998-12-07');
But, when we create a FTS table and insert text in UTF8.
CREATE VIRTUAL TABLE table1 USING FTS4(mytext,publishdate);
INSERT INTO table1 (mytext,publishdate) VALUES ('привет','1998-12-07');
and read the data with
SELECT mytext FROM table1
we get "??????".
The same commands in SQLITE Expert Personal return "привет". It means that in the table after Insert command we have 'привет' and select returns the data not in UTF8 encoding.
What may be done to get from the table correct value with Firedac
ADQuery.Open('SELECT mytext FROM table1')?
I think it is FireDac bug.
I've changed the following lines in ADSQLiteTypeName2ADDataType procedure of uADPhysSQLite.pas unit
SetLen(AOptions.FormatOptions.MaxStringSize, False);
AType := dtAnsiString;
to
SetLen(AOptions.FormatOptions.MaxStringSize, True);
AType := dtWideString;
for the case ABaseTypeName = 'VARCHAR'
and
SELECT mytext FROM table0
returns the correct value at runtime. But at design time still we have '??????'.
But I don't think it's a good solution.
I believe you should directly set parameter type as AsWideString:
Query.SQL.Text:='INSERT INTO table1 (mytext, publishdate) VALUES (:mytext,: publishdate);';
Query.Params[0].AsWideString := mytext;
Query.Params[1].AsDate := publishdate;
Query.ExecSQL;
Reference: http://docwiki.embarcadero.com/RADStudio/Rio/en/Unicode_Support_(FireDAC)#Parameter_Values

Update statement for a list of strings

I'm using sqlite3 and my table has a text field that actually has a list of strings.
So a sample select (select * from table where id=1) would return for example
1|foo#bar.com|21-03-2015|["foo", "bar", "foobar"]
I couldn't figure out how the sqlite statement for updating the list is though. I tried
update table set list="["foo", "bar"] where id=1;
update table set list=["foo", "bar"] where id=1;
update table set list="\["foo", "bar"\]" where id=1;
update table set list=(value) where id=1 VALUES (["foo", "bar"])
This is the statement you need:
UPDATE table SET list = '[\"foo\", \"bar\"]' WHERE id = 1

Sybase iq cannot load table with datetime column

I'm trying to load table to a sybase iq database from a text file, and have a trouble loading datetime field... Always get error data type conversion is not possible. I tried a lot of ways in solving it...
creating varchar field and converting it to data
creating temp table and inserting values into my table from temp table using dateformat, cast, convert,
load table table_name(
datetime_column datetime('dd-mm-yyyy hh-mm-ss')
) from ...
Nothing helps. Any help? thanks.
So I found the solution
load table table_name (
temp_date ' | ',
-- dt datetime column
)
from file_name
---------------------------------------
set dateformat dmy;
update table_name set dt = temp_date
ALTER TABLE table_name
DROP temp_date

How to have an automatic timestamp in SQLite?

I have an SQLite database, version 3 and I am using C# to create an application that uses this database.
I want to use a timestamp field in a table for concurrency, but I notice that when I insert a new record, this field is not set, and is null.
For example, in MS SQL Server if I use a timestamp field it is updated by the database and I don't have to set it by myself. Is this possible in SQLite?
Just declare a default value for a field:
CREATE TABLE MyTable(
ID INTEGER PRIMARY KEY,
Name TEXT,
Other STUFF,
Timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
However, if your INSERT command explicitly sets this field to NULL, it will be set to NULL.
You can create TIMESTAMP field in table on the SQLite, see this:
CREATE TABLE my_table (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name VARCHAR(64),
sqltime TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
INSERT INTO my_table(name, sqltime) VALUES('test1', '2010-05-28T15:36:56.200');
INSERT INTO my_table(name, sqltime) VALUES('test2', '2010-08-28T13:40:02.200');
INSERT INTO my_table(name) VALUES('test3');
This is the result:
SELECT * FROM my_table;
Reading datefunc a working example of automatic datetime completion would be:
sqlite> CREATE TABLE 'test' (
...> 'id' INTEGER PRIMARY KEY,
...> 'dt1' DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime')),
...> 'dt2' DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%S', 'now', 'localtime')),
...> 'dt3' DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'))
...> );
Let's insert some rows in a way that initiates automatic datetime completion:
sqlite> INSERT INTO 'test' ('id') VALUES (null);
sqlite> INSERT INTO 'test' ('id') VALUES (null);
The stored data clearly shows that the first two are the same but not the third function:
sqlite> SELECT * FROM 'test';
1|2017-09-26 09:10:08|2017-09-26 09:10:08|2017-09-26 09:10:08.053
2|2017-09-26 09:10:56|2017-09-26 09:10:56|2017-09-26 09:10:56.894
Pay attention that SQLite functions are surrounded in parenthesis!
How difficult was this to show it in one example?
Have fun!
you can use triggers. works very well
CREATE TABLE MyTable(
ID INTEGER PRIMARY KEY,
Name TEXT,
Other STUFF,
Timestamp DATETIME);
CREATE TRIGGER insert_Timestamp_Trigger
AFTER INSERT ON MyTable
BEGIN
UPDATE MyTable SET Timestamp =STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') WHERE id = NEW.id;
END;
CREATE TRIGGER update_Timestamp_Trigger
AFTER UPDATE On MyTable
BEGIN
UPDATE MyTable SET Timestamp = STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') WHERE id = NEW.id;
END;
To complement answers above...
If you are using EF, adorn the property with Data Annotation [Timestamp], then
go to the overrided OnModelCreating, inside your context class, and add this Fluent API code:
modelBuilder.Entity<YourEntity>()
.Property(b => b.Timestamp)
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken()
.ForSqliteHasDefaultValueSql("CURRENT_TIMESTAMP");
It will make a default value to every data that will be insert into this table.
you can use the custom datetime by using...
create table noteTable3
(created_at DATETIME DEFAULT (STRFTIME('%d-%m-%Y %H:%M', 'NOW','localtime')),
title text not null, myNotes text not null);
use 'NOW','localtime' to get the current system date else it will show some past or other time in your Database after insertion time in your db.
Thanks You...
If you use the SQLite DB-Browser you can change the default value in this way:
Choose database structure
select the table
modify table
in your column put under 'default value' the value: =(datetime('now','localtime'))
I recommend to make an update of your database before, because a wrong format in the value can lead to problems in the SQLLite Browser.

Resources