Beginner to SQLite/SQL. Building an Android app with FTS3 enabled, so I need to create virtual tables. I can't use this, because (according to my system log) virtual tables don't use IF NOT EXISTS syntax:
// Create the table if it doesn't exist.
db.transaction(function(tx){
tx.executeSql( 'CREATE TABLE IF NOT EXISTS User(UserId INTEGER NOT NULL PRIMARY KEY, FirstName TEXT NOT NULL, LastName TEXT NOT NULL)',[],nullHandler,errorHandler);
},errorHandler,successCallBack);
To confirm that my SQLite plug-in is working as expected, I have been using this instead:
// Create the table if it doesn't exist.
db.transaction(function(tx){
tx.executeSql( 'DROP TABLE User',[],nullHandler,errorHandler);
tx.executeSql( 'CREATE VIRTUAL TABLE User USING fts3 (UserId INTEGER NOT NULL PRIMARY KEY, FirstName TEXT NOT NULL, LastName TEXT NOT NULL)',[],nullHandler,errorHandler);
},errorHandler,successCallBack);
Which works mostly as expected (except that the UserId INTEGER NOT NULL PRIMARY KEY no longer works, returning null every time-- suggestions for a Virtual Table friendly way to add an incrementing integer also very welcome). But I don't want to drop the table every time, I want to keep it. How can I check for the existence of the table User and only create it if it doesn't exist?
According to the CREATE VIRTUAL TABLE documentation, the correct syntax is:
CREATE VIRTUAL TABLE IF NOT EXISTS User USING FTS4(...)
According to the FTS documentation, you cannot explicitly declare an autoincrementing column, but every table has an implicit column called docid or rowid.
Related
I am trying to insert on the virtual table only when the condition met to insert, like when the type is "-1" then only insert.
But it was inserting all the record
DROP TRIGGER if exists test_ai;
CREATE TRIGGER test_ai AFTER INSERT ON test
WHEN new.type = -1
BEGIN INSERT INTO
test_fts(body) VALUES (new.body);
END;
/*Create table */
CREATE TABLE `test` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `body` TEXT, `caption` TEXT, `type` INTEGER );
/*Create virtual table */
CREATE VIRTUAL TABLE test_fts USING fts5(body, content=test, content_rowid=id);
/* Insert into test table*/
insert into test(body, caption, type) values("5", "",-6);
It just looks like they're there, it's basically a virtual "copy" of the content table. However, only the rows inserted with the trigger will be returned in an FTS query. Try
SELECT * from test_fts where body MATCH '5'
It will not return the sample row. The trigger insert builds the FTS structure for the desired row(s).
I'm trying to set a default field in my table to current time. When I use a fts3 virtual table, inserting a row doesn't fill the default field to what it should be. Instead, it inserts null.
If I create the same table as normal table, the exact same query works and the field is populated.
Here are the 2 different table structures I'm using:
Normal table that default value does work
CREATE TABLE Emlak_test2 (_id INTEGER PRIMARY KEY,emlak_id TEXT,created_at TEXT DEFAULT (datetime('now', 'localtime')),emlak_sellorrent TEXT,emlak_cat TEXT,emlak_altcat TEXT,emlak_desc TEXT,emlak_living_rooms INTEGER,emlak_rooms INTEGER,emlak_sellprice INTEGER,emlak_temp TEXT,emlak_city TEXT,emlak_state TEXT,emlak_address TEXT,img_p1 TEXT,img_p2 TEXT,img_p3 TEXT,img_p4 TEXT,img_p5 TEXT,musteri_id TEXT);
FTS3 table that the default value does not work
CREATE VIRTUAL TABLE Emlak_test USING fts3 (_id INTEGER PRIMARY KEY,emlak_id TEXT,created_at TEXT DEFAULT (datetime('now', 'localtime')),emlak_sellorrent TEXT,emlak_cat TEXT,emlak_altcat TEXT,emlak_desc TEXT,emlak_living_rooms INTEGER,emlak_rooms INTEGER,emlak_sellprice INTEGER,emlak_temp TEXT,emlak_city TEXT,emlak_state TEXT,emlak_address TEXT,img_p1 TEXT,img_p2 TEXT,img_p3 TEXT,img_p4 TEXT,img_p5 TEXT,musteri_id TEXT);
Now, if I use this query;
insert into table_name default values;
on the first table, I can see that created_at field is populated. On the second table, the field is empty.
I hope you can help me with this.
Thank you!
The documentation says:
If column names are explicitly provided for the FTS table as part of the CREATE VIRTUAL TABLE statement, then a datatype name may be optionally specified for each column. This is pure syntactic sugar, the supplied typenames are not used by FTS or the SQLite core for any purpose. The same applies to any constraints specified along with an FTS column name – they are parsed but not used or recorded by the system in any way.
So it is not possible to have default values.
And,
it is not possible to create indices or triggers attached to FTS tables.
So it is not possible to work around this.
I have a table named groups, and I want to rename one of its columns. Is was ok, so far. I know sqlite doesn't support renaming columns, so I did:
ALTER TABLE groups RENAME to tmp_groups;
CREATE TABLE groups(
_ID integer primary key autoincrement,
new_column_name integer
);
INSERT INTO groups(_ID, new_column_name) SELECT _ID, old_column_name FROM tmp_groups;
DROP TABLE tmp_groups;
But, when I drop the table tmp_groups, the table members, that had a foreign key with ON DELETE CASCADE has its records deleted as well, so I had to do the following:
Create a table tmp_members with the same columns as members, and without the foreign key;
Insert the records from members in tmp_members;
Drop the table members;
Run the code from the first part (with the groups table);
Re-create the table members with its foreign key;
Insert in members data from tmp_members;
Man, that was tiring! Its too much code to simply rename a column;
Is there any simpler way to handle this constraint problem, or is this the "sqlite way"?
For historical reasons, SQLite allows to disable foreign key constraints (and this is even the default currently).
Just run PRAGMA foreign_keys = off before doing the groups table stuff.
It would also be possible to rename a column by using PRAGMA writable_schema, but you should do this only if you know what you're doing.
I have table with almost 200k entries. When I tried search with LIKE, it was very slow. Now I decided to use FTS. So I created two indexes where search will be held. Then I created fts virtual table.
`CREATE TABLE [search_eng] (
[id] INTEGER PRIMARY KEY AUTOINCREMENT,
[entry_id] INTEGER,
[re_value] TEXT,
[ke_value] TEXT,
[g_value] TEXT);
CREATE INDEX idx_se_re ON search_eng (re_value);
CREATE INDEX idx_se_gv ON search_eng (g_value);
CREATE VIRTUAL TABLE search_eng_fts USING fts3(id, entry_id, re_value, ke_value, g_value);`
I have no idea how to use new created FTS table. So my questions is how to use that virtual table to make search? Can you give an example?
This is explained in the documentation.
You do not need the two indexes for FTS searches.
You should declare the id column as INTEGER PRIMARY KEY.
You probably don't need the entry_id column in the FST table.
Copy the text into the FTS table:
INSERT INTO search_eng_fts(id, re_value, ke_value, g_value)
SELECT id, re_value, ke_value, g_value FROM search_eng;
Then you can use the MATCH operator to search in that table:
SELECT id FROM search_eng_fts WHERE re_value MATCH 'hello';
I'm trying to create a table and I've tried so many times to figure this out... for some reason it won't accept this.. it's saying something about the auto_increment
create table if not exists Assignments(
id auto_increment primary key,
class_name VARCHAR(30),
assignment_name VARCHAR(30) not null,
due_date VARCHAR(30) not null,
notes VARCHAR(30));
whats the problem?
EDIT: i am trying to use SQLite eventually but this command was written on my mySQL thru WAMP
First of all, Android uses SQLite, so your mysql tag is slightly incorrect unless I'm missing something you're doing.
Secondly, you would say
CREATE TABLE ASSIGNMENTS(id INTEGER PRIMARY KEY, class_name TEXT, assignment_name TEXT NOT NULL, due_date TEXT NOT NULL, notes TEXT);
"autoincrement" is handled automatically if you set your primary key as an INTEGER type, even though under the covers SQLite uses strings for everything
reference: SQLite datatypes
further reference: INTEGER PRIMARY KEY
Even more reference: "If an INSERT statement attempts to insert a NULL value into a rowid or integer primary key column, the system chooses an integer value to use as the rowid automatically. A detailed description of how this is done is provided separately."
It is autoincrement, not auto_increment