Is it possible to run CQL3 queries "create table", "insert into" with Astyanax? - astyanax

For now I have found just "select" examples.
Or is it possible to do with e.g. MutationBatch?
MutationBatch m = keyspace.prepareMutationBatch();
ColumnListMutation<String> cfmStandard = m.withRow(MY_CF, ...);
my column family is:
CREATE TABLE my_cf (
... key text,
... timeid timeuuid,
... flag boolean,
... data text,
... PRIMARY KEY (key, timeid));

worked for inserts and create:
keyspace.prepareQuery(MY_CF).withCql(queryBuilder.toString()).execute();

Related

How do i get sqlite to preserve string-type when it contains numbers only?

When i create a table with a STRING field with the nativescript-sqlite plugin, and enter a string "000123" (any string containing numbers only), and later fe3tch the record from the DB, it returns an int (123) and does not persist the string type. Is there any trick for this ? I enclose the code i use for creating, saving and returning the field....
creating the table ( the code has been abreviated )
var Name = 'users';
var TableDef = MedID INT, Naam STRING ,Pin STRING';
db.execSQL("CREATE TABLE IF NOT EXISTS " + Name +
"(id INTEGER PRIMARY KEY AUTOINCREMENT," + TableDef + " )")
.then(result => {...} );
Inserting a record
db.execSQL( "INSERT INTO users (MedID,Naam,Pin) VALUES (?, ?,?)",
[1,'John Doe','000123'] )
.then(id => {...} );
returning the pincode
var db_name = "scanapp.db";
new sqlite(db_name).then(db =>
{
db.all('select MedID, Naam, Pin from users order by ID ')
.then (rows => { console.log (rows[0][2]); });
});
The problem is in your table definition. Your Pin column was given a type of STRING.
In Sqlite, a column type is used to set the affinity of that column and control the preferred way to store values in that column. If you look at the rules for determining affinity type based on column type, you'll see that the type STRING defaults to the NUMERIC affinity, which means:
A column with NUMERIC affinity may contain values using all five storage classes. When text data is inserted into a NUMERIC column, the storage class of the text is converted to INTEGER or REAL (in order of preference) if such conversion is lossless and reversible.
The interesting thing here is the lossless and reversible bit, because this clearly isn't thanks to the leading 0's being stripped. I suspect that's a bug.
Anyways, the fix is to change your table definition to use types that have TEXT affinity - like TEXT, CHAR, etc, instead of the current STRING:
sqlite> create table foo(bar text, baz string);
sqlite> insert into foo values ('0012', '0012');
sqlite> select bar, typeof(bar), baz, typeof(baz) from foo;
bar typeof(bar) baz typeof(baz)
---------- ----------- ---------- -----------
0012 text 12 integer
Does the INSERT command execute without throwing any exceptions? I'm asking because you are explicitly inserting the MedID which is the table's primary AUTOINCREMENT field.
Your INSERT statement should be like:
db.execSQL("insert into users (Naam, Pin) values (?, ?)", ["John Doe", "000123"], function(err, id) {
console.log("The new record id is:", id);
});
Always check the err to make sure whether your command is successfully executed or not.
if (err) {
console.error("Failed to insert!", err);
} else {
console.log("The new record id is:", id);
}
Please check the NativeScript sqlite documentation for much more useful info.
Good luck.

Except the name of table what property can use to differentiate these tables

I have a database which contains many tables and these tables can be added or removedd any time.So I give each of them a different name like Table1,Table2,...
but it's uncomfortable to use these table because sometime I forget what infomation was stored in Table1
So I want something to differentiate these all tables, some property that I can be specified when I create a table and I can use to access a specific table when I need to fetch informations from that table
As one comment says, you could create a table for notes on the other tables:
CREATE TABLE notes (
id INT AUTO_INCREMENT,
table_name VARCHAR(64),
note VARCHAR(255),
PRIMARY KEY (id)
);
By the way, MySQL (but not SQLite) allows comments on the table itself:
CREATE TABLE table1 (
id INT AUTO_INCREMENT,
val INT,
PRIMARY KEY (id)
) COMMENT = 'Table of stuff';
-- Show the comment
SHOW TABLE STATUS WHERE NAME='table1';
-- Just show names and comments
SELECT `TABLE_NAME`, `TABLE_COMMENT`
FROM information_schema.tables
WHERE table_schema = DATABASE();

How to autogenerate the username with specific string?

I am using asp.net2008 and MY SQL.
I want to auto-generate the value for the field username with the format as
"SISI001", "SISI002",
etc. in SQL whenever the new record is going to inserted.
How can i do it?
What can be the SQL query ?
Thanks.
Add a column with auto increment integer data type
Then get the maximum value of that column in the table using "Max()" function and assign the value to a integer variable (let the variable be 'x').
After that
string userid = "SISI";
x=x+1;
string count = new string('0',6-x.ToString().length);
userid=userid+count+x.ToString();
Use userid as your username
Hope It Helps. Good Luck.
PLAN A>
You need to keep a table (keys) that contains the last numeric ID generated for various entities. This case the entity is "user". So the table will contain two cols viz. entity varchar(100) and lastid int.
You can then have a function written that will receive the entity name and return the incremented ID. Use this ID concatenated with the string component "SISI" to be passed to MySQL for insertion to the database.
Following is the MySQL Table tblkeys:
CREATE TABLE `tblkeys` (
`entity` varchar(100) NOT NULL,
`lastid` int(11) NOT NULL,
PRIMARY KEY (`entity`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The MySQL Function:
DELIMITER $$
CREATE FUNCTION `getkey`( ps_entity VARCHAR(100)) RETURNS INT(11)
BEGIN
DECLARE ll_lastid INT;
UPDATE tblkeys SET lastid = lastid+1 WHERE tblkeys.entity = ps_entity;
SELECT tblkeys.lastid INTO ll_lastid FROM tblkeys WHERE tblkeys.entity = ps_entity;
RETURN ll_lastid;
END$$
DELIMITER ;
The sample function call:
SELECT getkey('user')
Sample Insert command:
insert into users(username, password) values ('SISI'+getkey('user'), '$password')
Plan B>
This way the ID will be a bit larger but will not require any extra table. Use the following SQL to get a new unique ID:
SELECT ROUND(NOW() + 0)
You can pass it as part of the insert command and concatenate it with the string component of "SISI".
I am not an asp.net developer but i can help you
You can do something like this...
create a sequence in your mysql database as-
CREATE SEQUENCE "Database_name"."SEQUENCE1" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 001 START WITH 21 CACHE 20 NOORDER NOCYCLE ;
and then while inserting use this query-----
insert into testing (userName) values(concat('SISI', sequence1.nextval))
may it help you in your doubt...
Try this:
CREATE TABLE Users (
IDs int NOT NULL IDENTITY (1, 1),
USERNAME AS 'SISI' + RIGHT('000000000' + CAST(IDs as varchar(10)), 4), --//getting uniqueness of IDs field
Address varchar(150)
)
(not tested)

SQLite query to find primary keys

In SQLite I can run the following query to get a list of columns in a table:
PRAGMA table_info(myTable)
This gives me the columns but no information about what the primary keys may be. Additionally, I can run the following two queries for finding indexes and foreign keys:
PRAGMA index_list(myTable)
PRAGMA foreign_key_list(myTable)
But I cannot seem to figure out how to view the primary keys. Does anyone know how I can go about doing this?
Note: I also know that I can do:
select * from sqlite_master where type = 'table' and name ='myTable';
And it will give the the create table statement which shows the primary keys. But I am looking for a way to do this without parsing the create statement.
The table_info DOES give you a column named pk (last one) indicating if it is a primary key (if so the index of it in the key) or not (zero).
To clarify, from the documentation:
The "pk" column in the result set is zero for columns that are not
part of the primary key, and is the index of the column in the primary
key for columns that are part of the primary key.
Hopefully this helps someone:
After some research and pain the command that worked for me to find the primary key column name was:
SELECT l.name FROM pragma_table_info("Table_Name") as l WHERE l.pk = 1;
For the ones trying to retrieve a pk name in android, and while using the ROOM library.
#Oogway101's answer was throwing an error: "no such column [your_table_name] ... etc.. etc...
my way of query submition was:
String pkSearch = "SELECT l.name FROM pragma_table_info(" + tableName + ") as l WHERE l.pk = 1;";
database.query(new SimpleSQLiteQuery(pkSearch)
I tried using the (") quotations and still error.
String pkSearch = "SELECT l.name FROM pragma_table_info(\"" + tableName + "\") as l WHERE l.pk = 1;";
So my solution was this:
String pragmaInfo = "PRAGMA table_info(" + tableName + ");";
Cursor c = database.query(new SimpleSQLiteQuery(pragmaInfo));
String id = null;
c.moveToFirst();
do {
if (c.getInt(5) == 1) {
id = c.getString(1);
}
} while (c.moveToNext() && id == null);
Log.println(Log.ASSERT, TAG, "AbstractDao: pk is: " + id);
The explanation is that:
A) PRAGMA table_info returns a cursor with various indices, the response is atleast of length 6... didnt check more...
B) index 1 has the column name.
C) index 5 has the "pk" value, either 0 if it is not a primary key, or 1 if its a pk.
You can define more than one pk so this will not bring an accurate result if your table has more than one (IMHO more than one is bad design and balloons the complexity of the database beyond human comprehension).
So how will this fit into the #Dao? (you may ask...)
When making the Dao "abstract" you have access to a default constructor which has the database in it:
from the docummentation:
An abstract #Dao class can optionally have a constructor that takes a Database as its only parameter.
this is the constructor that will grant you access to the query.
There is a catch though...
You may use the Dao during a database creation with the .addCallback() method:
instance = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase2.class, "database")
.addCallback(
//You may use the Daos here.
)
.build();
If you run a query in the constructor of the Dao, the database will enter a feedback loop of infinite instantiation.
This means that the query MUST be used LAZILY (just at the moment the user needs something), and because the value will never change, it can be stored. and never re-queried.

SQLite add Primary Key

I created a table in Sqlite by using the CREATE TABLE AS syntax to create a table based on a SELECT statement. Now this table has no primary key but I would like to add one.
Executing ALTER TABLE table_name ADD PRIMARY KEY(col1, col2,...) gives a syntax error "near PRIMARY"
Is there a way to add a primary key either during table creation or afterwards in Sqlite?
By "during creation" I mean during creation with CREATE TABLE AS.
You can't modify SQLite tables in any significant way after they have been created. The accepted suggested solution is to create a new table with the correct requirements and copy your data into it, then drop the old table.
here is the official documentation about this: http://sqlite.org/faq.html#q11
As long as you are using CREATE TABLE, if you are creating the primary key on a single field, you can use:
CREATE TABLE mytable (
field1 TEXT,
field2 INTEGER PRIMARY KEY,
field3 BLOB,
);
With CREATE TABLE, you can also always use the following approach to create a primary key on one or multiple fields:
CREATE TABLE mytable (
field1 TEXT,
field2 INTEGER,
field3 BLOB,
PRIMARY KEY (field2, field1)
);
Reference: http://www.sqlite.org/lang_createtable.html
This answer does not address table alteration.
I tried to add the primary key afterwards by changing the sqlite_master table directly.
This trick seems to work.
It is a hack solution of course.
In short: create a regular (unique) index on the table, then make the schema writable and change the name of the index to the form reserved by sqlite to identify a primary key index, (i.e. sqlite_autoindex_XXX_1, where XXX is the table name) and set the sql string to NULL. At last change the table definition itself.
One pittfal: sqlite does not see the index name change until the database is reopened. This seems like a bug, but not a severe one (even without reopening the database, you can still use it).
Suppose the table looks like:
CREATE TABLE tab1(i INTEGER, j INTEGER, t TEXT);
Then I did the following:
BEGIN;
CREATE INDEX pk_tab1 ON tab1(i,j);
pragma writable_schema=1;
UPDATE sqlite_master SET name='sqlite_autoindex_tab1_1',sql=null WHERE name='pk_tab1';
UPDATE sqlite_master SET sql='CREATE TABLE tab1(i integer,j integer,t text,primary key(i,j))' WHERE name='tab1';
COMMIT;
Some tests (in sqlite shell):
sqlite> explain query plan select * from tab1 order by i,j;
0|0|0|SCAN TABLE tab1 USING INDEX sqlite_autoindex_tab1_1
sqlite> drop index sqlite_autoindex_tab1_1;
Error: index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped
According to the sqlite docs about table creation, using the create table as select produces a new table without constraints and without primary key.
However, the documentation also says that primary keys and unique indexes are logically equivalent (see constraints section):
In most cases, UNIQUE and PRIMARY KEY constraints are implemented by creating a unique index in the database. (The exceptions are INTEGER PRIMARY KEY and PRIMARY KEYs on WITHOUT ROWID tables.) Hence, the following schemas are logically equivalent:
CREATE TABLE t1(a, b UNIQUE);
CREATE TABLE t1(a, b PRIMARY KEY);
CREATE TABLE t1(a, b);
CREATE UNIQUE INDEX t1b ON t1(b);
So, even if you cannot alter your table definition through SQL alter syntax, you can get the same primary key effect through the use a unique index.
Also, any table (except those created without the rowid syntax) have an inner integer column known as "rowid". According to the docs, you can use this inner column to retrieve/modify record tables.
You can do it like this:
CREATE TABLE mytable (
field1 text,
field2 text,
field3 integer,
PRIMARY KEY (field1, field2)
);
sqlite> create table t(id integer, col2 varchar(32), col3 varchar(8));
sqlite> insert into t values(1, 'he', 'ha');
sqlite>
sqlite> create table t2(id integer primary key, col2 varchar(32), col3 varchar(8));
sqlite> insert into t2 select * from t;
sqlite> .schema
CREATE TABLE t(id integer, col2 varchar(32), col3 varchar(8));
CREATE TABLE t2(id integer primary key, col2 varchar(32), col3 varchar(8));
sqlite> drop table t;
sqlite> alter table t2 rename to t;
sqlite> .schema
CREATE TABLE IF NOT EXISTS "t"(id integer primary key, col2 varchar(32), col3 varchar(8));
Introduction
This is based on Android's java and it's a good example on changing the database without annoying your application fans/customers. This is based on the idea of the SQLite FAQ page
http://sqlite.org/faq.html#q11
The problem
I did not notice that I need to set a row_number or record_id to delete a single purchased item in a receipt, and at same time the item barcode number fooled me into thinking of making it as the key to delete that item. I am saving a receipt details in the table receipt_barcode. Leaving it without a record_id can mean deleting all records of the same item in a receipt if I used the item barcode as the key.
Notice
Please understand that this is a copy-paste of my code I am work on at the time of this writing. Use it only as an example, copy-pasting randomly won't help you. Modify this first to your needs
Also please don't forget to read the comments in the code .
The Code
Use this as a method in your class to check 1st whether the column you want to add is missing . We do this just to not repeat the process of altering the table receipt_barcode.
Just mention it as part of your class. In the next step you'll see how we'll use it.
public boolean is_column_exists(SQLiteDatabase mDatabase , String table_name,
String column_name) {
//checks if table_name has column_name
Cursor cursor = mDatabase.rawQuery("pragma table_info("+table_name+")",null);
while (cursor.moveToNext()){
if (cursor.getString(cursor.getColumnIndex("name")).equalsIgnoreCase(column_name)) return true;
}
return false;
}
Then , the following code is used to create the table receipt_barcode if it already does NOT exit for the 1st time users of your app. And please notice the "IF NOT EXISTS" in the code. It has importance.
//mDatabase should be defined as a Class member (global variable)
//for ease of access :
//SQLiteDatabse mDatabase=SQLiteDatabase.openOrCreateDatabase(dbfile_path, null);
creation_query = " CREATE TABLE if not exists receipt_barcode ( ";
creation_query += "\n record_id INTEGER PRIMARY KEY AUTOINCREMENT,";
creation_query += "\n rcpt_id INT( 11 ) NOT NULL,";
creation_query += "\n barcode VARCHAR( 255 ) NOT NULL ,";
creation_query += "\n barcode_price VARCHAR( 255 ) DEFAULT (0),";
creation_query += "\n PRIMARY KEY ( record_id ) );";
mDatabase.execSQL(creation_query);
//This is where the important part comes in regarding the question in this page:
//adding the missing primary key record_id in table receipt_barcode for older versions
if (!is_column_exists(mDatabase, "receipt_barcode","record_id")){
mDatabase.beginTransaction();
try{
Log.e("record_id", "creating");
creation_query="CREATE TEMPORARY TABLE t1_backup(";
creation_query+="record_id INTEGER PRIMARY KEY AUTOINCREMENT,";
creation_query+="rcpt_id INT( 11 ) NOT NULL,";
creation_query+="barcode VARCHAR( 255 ) NOT NULL ,";
creation_query+="barcode_price VARCHAR( 255 ) NOT NULL DEFAULT (0) );";
mDatabase.execSQL(creation_query);
creation_query="INSERT INTO t1_backup(rcpt_id,barcode,barcode_price) SELECT rcpt_id,barcode,barcode_price FROM receipt_barcode;";
mDatabase.execSQL(creation_query);
creation_query="DROP TABLE receipt_barcode;";
mDatabase.execSQL(creation_query);
creation_query="CREATE TABLE receipt_barcode (";
creation_query+="record_id INTEGER PRIMARY KEY AUTOINCREMENT,";
creation_query+="rcpt_id INT( 11 ) NOT NULL,";
creation_query+="barcode VARCHAR( 255 ) NOT NULL ,";
creation_query+="barcode_price VARCHAR( 255 ) NOT NULL DEFAULT (0) );";
mDatabase.execSQL(creation_query);
creation_query="INSERT INTO receipt_barcode(record_id,rcpt_id,barcode,barcode_price) SELECT record_id,rcpt_id,barcode,barcode_price FROM t1_backup;";
mDatabase.execSQL(creation_query);
creation_query="DROP TABLE t1_backup;";
mDatabase.execSQL(creation_query);
mdb.setTransactionSuccessful();
} catch (Exception exception ){
Log.e("table receipt_bracode", "Table receipt_barcode did not get a primary key (record_id");
exception.printStackTrace();
} finally {
mDatabase.endTransaction();
}
I had the same problem and the best solution I found is to first create the table defining primary key and then to use insert into statement.
CREATE TABLE mytable (
field1 INTEGER PRIMARY KEY,
field2 TEXT
);
INSERT INTO mytable
SELECT field1, field2
FROM anothertable;
CREATE TABLE tablename(
Column1 INTEGER PRIMARY KEY,
Column2 VARCHAR(50)
)
INSERT INTO tablename
SELECT Column1 , Column2
FROM ANOTHERTABLE
I used the CREATE TABLE AS syntax to merge several columns and encountered the same problem. Here is an AppleScript I wrote to speed the process up.
set databasePath to "~/Documents/Databases/example.db"
set tableOne to "separate" -- Table from which you are pulling data
set tableTwo to "merged" -- Table you are creating
set {tempCol, tempColEntry, permColEntry} to {{}, {}, {}}
set permCol to {"id integer primary key"}
-- Columns are created from single items AND from the last item of a list
-- {{"a", "b", "c"}, "d", "e"} Columns "a" and "b" will be merged into a new column "c". tableTwo will have columns "c", "d", "e"
set nonCoal to {"City", "Contact", "Names", {"Address 1", "Address", "address one", "Address1", "Text4", "Address 1"}, {"E-Mail", "E-Mail Address", "Email", "Email Address", "EmailAddress", "Email"}, {"Zip", "Zip Code", "ZipCode", "Zip"}, {"Telephone", "BusinessPhone", "Phone", "Work Phone", "Telephone"}, {"St", "State", "State"}, {"Salutation", "Mr/Ms", "Mr/s", "Salutations", "Sautation", "Salutation"}}
-- Build the COALESCE statements
repeat with h from 1 to count of nonCoal
set aColumn to item h of nonCoal
if class of aColumn is not list then
if (count of words of aColumn) > 1 then set aColumn to quote & aColumn & quote
set end of tempCol to aColumn
set end of permCol to aColumn
else
set coalEntry to {}
repeat with i from 1 to count of aColumn
set coalCol to item i of aColumn as string
if (count of words of coalCol) > 1 then set coalCol to quote & coalCol & quote
if i = 1 then
set end of coalEntry to "TRIM(COALESCE(" & coalCol & ", '') || \" \" || "
else if i < ((count of aColumn) - 1) then
set end of coalEntry to "COALESCE(" & coalCol & ", '') || \" \" || "
else if i = ((count of aColumn) - 1) then
set as_Col to item (i + 1) of aColumn as string
if (count of words of as_Col) > 1 then set as_Col to quote & as_Col & quote
set end of coalEntry to ("COALESCE(" & coalCol & ", '')) AS " & as_Col) & ""
set end of permCol to as_Col
end if
end repeat
set end of tempCol to (coalEntry as string)
end if
end repeat
-- Since there are ", '' within the COALESCE statement, you can't use "TID" and "as string" to convert tempCol and permCol for entry into sqlite3. I rebuild the lists in the next block.
repeat with j from 1 to count of tempCol
if j < (count of tempCol) then
set end of tempColEntry to item j of tempCol & ", "
set end of permColEntry to item j of permCol & ", "
else
set end of tempColEntry to item j of tempCol
set end of permColEntry to item j of permCol
end if
end repeat
set end of permColEntry to ", " & item (j + 1) of permCol
set permColEntry to (permColEntry as string)
set tempColEntry to (tempColEntry as string)
-- Create the new table with an "id integer primary key" column
set createTable to "create table " & tableTwo & " (" & permColEntry & "); "
do shell script "sqlite3 " & databasePath & space & quoted form of createTable
-- Create a temporary table and then populate the permanent table
set createTemp to "create temp table placeholder as select " & tempColEntry & " from " & tableOne & "; " & "insert into " & tableTwo & " select Null, * from placeholder;"
do shell script "sqlite3 " & databasePath & space & quoted form of createTemp
--export the new table as a .csv file
do shell script "sqlite3 -header -column -csv " & databasePath & " \"select * from " & tableTwo & " ; \"> ~/" & tableTwo & ".csv"

Resources