How shall I design this database? - sqlite

So I've got to design a table for clients with fields (Id, name, bla, bla, Phone numbers). The last field terrifies me as there is not only one number, but many. I see 3 ways to accomplish this task
The field is String. Anytime before an insert, the String array of phone numbers is encoded using a delimiter ';' and thereafter inserted as String.
The field is BLOB. The string array is directly stored (no idea if this is possible in sqlite).
Create another table for Phone numbers with field (ClientId, PhoneNumber).
What seems the best approach?

As it is bad practice to store multiple values in one field, the third option stated is the regular way to go.

Related

Sqlite sequence not associated with an auto-increment column

I've got a situation where I need to generate a unique id for use across multiple tables, something like tables A, B, C each having a uniqueId field. For business reasons, the id's have to be unique across all tables, but because of the multiple tables, I can't use an auto-increment column.
Is there a way to make a sequence that can be shared like this?
(I know I could just make the uniqueId column TEXT and store a GUID in there, and that would be unique, but I may have a LOT of these, and I'd rather use a 4 byte integer than a 32 byte GUID for this. Is there a more compact way to generate a non-conflicting identifier in sqlite?)
Traditionally you'd use a sequence; just an auto-incrementing counter. Unfortunately, SQLite doesn't support sequences.
Use a Universally Unique Identifier, a UUID. UUIDv4 is just a 128 bit random number. Generate it in your program and insert it; preferably insert it as a 128 bit value, not a as string.
Create another table with just an autoinc column (and maybe one other column, if SQLite won't let you have just one?), and triggers for inserts on the other tables that:
First inserts a row in this "fake-sequence" table
Then fetches the last inserted row's id from that table
And finally inserts that "fake-sequence-table"-generated value into the global-id columns of the other tables.
Should work -- if SQLite has triggers.

Searching for blob field in SQLite

I have column in my database that stores BLOB.
I want to run a query to check if specific byte array value is present in the table.
The value is b'\xf4\x8f\xc6{\xc2mH(\x97\x9c\x83hkE\x8b\x95' (python bytes).
I tried to run this query:
SELECT * from received_message
WHERE "EphemeralID"
LIKE HEX('\xf4\x8f\xc6{\xc2mH(\x97\x9c\x83hkE\x8b\x95');
But I get 0 results though I 100% sure that I store this value in the database.
Is there something wrong with my query?
Your search string is a bit weird-- you appear to have some complex things in there like { and (. Maybe you should search through the blob the way it is stored instead?
From the Sqlite documentation:
BLOB literals are string literals containing hexadecimal data and
preceded by a single "x" or "X" character. Example: X'53514C697465'
So maybe do a like with the ascii representation of the hex value you want? Maybe start with looking for just f48f or F48F if your sqlite stores it upper case.

How is an MVCCKey formed in CockroachDB?

I want to create a MVCCKey with a timestamp and pretty value I know. But I realize a roachpb.key is not very straightforward; is there some prefix/suffix involved? Is the database name is also encoded in roachpb.key?
Can anyone please tell me how a MVCCKey is formed? What information does it have? In the documentation, it just says that it looks like /table/primary/key/column.
An engine.MVCCKey combines a regular key with a timestamp. MVCCKeys are encoded into byte strings for use as RockDB keys (RocksDB is configured with a custom comparator so MVCCKeys are sorted correctly even though the timestamp uses a variable-width encoding).
Regular keys are byte strings of type roachpb.Key. For ordinary data records, the keys are constructed from table, column, and index IDs, along with the values of indexed columns. (The database ID is not included here; the database to which a table belongs can be found in the system.descriptors table)
The function keys.PrettyPrint can convert a roachpb.Key to a human-readable form.

DataColumn.Expression RowFilter on Dataview

Maybe this is stupid question or maybe I have designed my code completely wrong but anyhow, here is my question...
I have a "dynamic" sql-query where its impossible to take all the parameters i need for making the query parameterized, therefore i get my data and put it in a dataview and after that i search for the rows I want to show in the dataview.
One of the columns are a column named id. Id is primary key and auto_increment in the table and therefore it's an int.
Now to my question, i want to present all my matching id with the number the user put in my textbox. Let us say my id consist of 5 numbers and the user put the 4 first, then in the perfect world i would have 10 matches (12340-12349 as an example). Doing this on a string is very easy using RowFilter and the operator LIKE combined with a wildcard. But how can i do something similar on integers? Do i have to convert it to strings and wont that ruin the rowfilter expression?
Not a live or death-situation... im more curious if the ice im walking is very thin... :)
Rowfilter expression supports CONVERT function, so technically you can convert your integer ID to string to do the LIKE command:
MyDataView.RowFilter = "Convert(ID, 'System.String') LIKE '1234*'";
But do try to offload the filtering to backend. It's unlikely that you have unlimited number of parameters and SQL is very flexible in allowing you different combinations.

Why does SQLite full-text search (FTS4) treat angle brackets differently in a compound search?

I have an SQLite database using FTS4. It is used to store emails with message id's of the form:
Searching for messages using the FTS MATCH syntax, I get a result from:
SELECT rowid FROM emails WHERE emails MATCH '<8200#comms.io>'
This returns the correct row. But when I try to find multiple emails, I get an empty response:
SELECT rowid FROM emails WHERE emails MATCH '<8200#comms.io> OR <8188#comms.io>'
Strangely though, I can search without the angle bracket characters. This returns both rows:
SELECT rowid FROM emails WHERE emails MATCH '8200#comms.io OR 8188#comms.io'
This even though the angle brackets are present in the stored columns. I can find no mention that these are special characters in SQLite, and without the 'OR', the single-term search works fine.
Why are these characters treated differently in my compound search?
The default (simple) tokenizer reads alphanumerical characters and treats all others as word separators to be ignored.
So when searching for a message ID, you have to actually search for a phrase with multiple words (8200, comms, and io).
If you want to treat the entire message ID as a word, you have to write a custom tokenizer.

Resources