[sqlite] Best way to handle time slicing of SQL data.

2015-06-02 Thread Richard Warburton
Hi,

I'm wanting to store data in a way such that I can choose a time in the
past and view records as they were at that dateTime.  Therefore (in my
mind), all updates are really inserts with a timestamp.  Ids are suddenly
no longer primary keys, as many records can have the same id, but a new
entry must be given a unique id (otherwise it will look like an update for
an existing entry).

Here's a very simplified view of what I'm currently doing:
CREATE TABLE data (
UID INTEGER PRIMARY KEY AUTOINCREMENT,
Id INTEGER NOT NULL DEFAULT 0, -- shared by updates of the same data entry

Data TEXT,
User INT, -- who made this update
At INT, -- when the update was made
Remove INT NOT NULL DEFAULT 0 -- set to 1 if data entry has been deleted
);

My initial questions are:
1) Do I need UID?  I'm currently using it to ensure a unique Id for when
the user is creating a new entry.  This however means two operations, an
Insert, then an Update to set the record's Id to match its UID. It also has
the overhead of autoincrement, ensuring that UID is never ever reused and
only goes upwards (I'm currently using MAX(UID)  to get the latest record
<= the time I'm interested in.  I guess there's no extra storage as rowid
would exist anyway.
2) Can I auto fill Id to UID on insert instead of having to do two
operations?
3) Am I on track or is there a better way to approach this problem?

Thanks in advance for any feedback.

-- 
Richard Warburton


[sqlite] Best way to handle time slicing of SQL data.

2015-06-02 Thread Simon Slavin

On 2 Jun 2015, at 12:34pm, Richard Warburton  
wrote:

> I'm wanting to store data in a way such that I can choose a time in the
> past and view records as they were at that dateTime.  Therefore (in my
> mind), all updates are really inserts with a timestamp.  Ids are suddenly
> no longer primary keys, as many records can have the same id, but a new
> entry must be given a unique id (otherwise it will look like an update for
> an existing entry).

This is an area I used to do a lot of work in, and there are some complicated 
security implications I'm not going to try to explore in one post.  If you have 
a specific question I'll try to answer it, but here are my general 
recommendations:

Keep your existing tables as they are, modify them as you have been, and create 
a new table or tables for the historical information.  That way, parts of your 
code which don't care about historical information can continue to look at the 
'normal' tables as they did previously, and you have the same uncomplicated 
'id' system that would be used in a normal database.

When you have commands which modify the logged table, use an AFTER TRIGGER to 
make a copy of the new row into this new table, with a timestamp on it.  The 
primary key of this new table becomes (truerowid, timestamp).  Of course, 
DELETE FROM doesn't leave a 'new row', so you will invent a way to record 
DELETEs.

As an alternative, rather than logging copies of the actual data in this new 
table, you can keep copies of the commands used to change the table.  If you do 
this, then you can create a copy of your database at any time merely by 
replaying all the commands executed up to that time.  One advantage of this is 
that all your reconstruction information can be stored in one table.

Which of these you do depends on why you're keeping the historical data: 
whether you're trying to keep an 'changes list' for audit/security purposes or 
whether you expect to actually be working on the data in the same way as you 
work on current data.

Simon.


[sqlite] sqlite3 compound index usage for LIKE and GROUP BY

2015-06-02 Thread Simon Slavin

On 1 Jun 2015, at 7:37pm, Amol Kandurwar  wrote:

> SELECT foo, boo FROM mytable WHERE foo LIKE 'hi%' GROUP BY boo;

Try the following:

CREATE INDEX m_fb ON mytable (foo, boo);
CREATE INDEX m_bf ON mytable (boo, foo);
ANALYZE;
SELECT foo, boo FROM mytable WHERE foo BETWEEN 'hi' AND 'hizzz' GROUP BY boo;

See what happens.  Use the results of that to work to wards a more convenient 
solution.

Simon.


[sqlite] How to get length of all columns in a table

2015-06-02 Thread Drago, William @ CSG - NARDA-MITEQ
All,

I just want to make sure everyone understands that I know how to get the length 
of a column and that I was only asking for a wildcard technique to get the 
lengths of all columns in a table without having to list all the columns (e.g. 
SELECT Length(*) FROM myTable). Obviously that doesn't work, but that's the 
kind of thing I was looking for.

I already wrote a little code snippet to automatically generate a "SELECT 
Length(col_1), Length(col_2...)" string from the table def, and I'm happy with 
that solution.

I am using this on BLOBs and Length() is returning the number of bytes, which 
is exactly what I need.

All is well. Thanks for all your input,

--
Bill Drago
Senior Engineer
L3 Narda-MITEQ
435 Moreland Road
Hauppauge, NY 11788
631-272-5947 / William.Drago at L-3COM.com



> -Original Message-
> From: sqlite-users-bounces at mailinglists.sqlite.org [mailto:sqlite-
> users-bounces at mailinglists.sqlite.org] On Behalf Of Richard Hipp
> Sent: Tuesday, June 02, 2015 9:15 AM
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] How to get length of all columns in a table
>
> On 6/2/15, Igor Tandetnik  wrote:
> > On 6/2/2015 2:28 AM, Hick Gunter wrote:
> >> Sqlite3_column_bytes will convert numeric values to strings and
> >> return the length of that "string representation" (excluding the
> >> terminating \0), not the byte size required to store the numeric
> value itself.
> >
> > So will length() SQL function, I'm pretty sure.
>
> Yes, both length() and sqlite3_column_bytes() will convert numbers to
> strings before computing the length.  However, they are not equivalent.
>
> The length() SQL function returns the number of *characters*.  The
> sqlite3_column_bytes() C function returns the number of *bytes*.
>
> --
> D. Richard Hipp
> drh at sqlite.org
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
CONFIDENTIALITY, EXPORT CONTROL AND DISCLAIMER NOTE:This e-mail and any 
attachments are solely for the use of the addressee and may contain information 
that is privileged or confidential. Any disclosure, use or distribution of the 
information contained herein is prohibited. In the event this e-mail contains 
technical data within the definition of the International Traffic in Arms 
Regulations or Export Administration Regulations, it is subject to the export 
control laws of the U.S.Government. The recipient should check this e-mail and 
any attachments for the presence of viruses as L-3 does not accept any 
liability associated with the transmission of this e-mail. If you have received 
this communication in error, please notify the sender by reply e-mail and 
immediately delete this message and any attachments.


[sqlite] How to get length of all columns in a table

2015-06-02 Thread Hick Gunter
True. Both are documented to convert their argument to string (unless it is 
already a string or blob).

-Urspr?ngliche Nachricht-
Von: Igor Tandetnik [mailto:igor at tandetnik.org]
Gesendet: Dienstag, 02. Juni 2015 14:21
An: sqlite-users at mailinglists.sqlite.org
Betreff: Re: [sqlite] How to get length of all columns in a table

On 6/2/2015 2:28 AM, Hick Gunter wrote:
> Sqlite3_column_bytes will convert numeric values to strings and return the 
> length of that "string representation" (excluding the terminating \0), not 
> the byte size required to store the numeric value itself.

So will length() SQL function, I'm pretty sure.
--
Igor Tandetnik

___
sqlite-users mailing list
sqlite-users at mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


___
 Gunter Hick
Software Engineer
Scientific Games International GmbH
FN 157284 a, HG Wien
Klitschgasse 2-4, A-1130 Vienna, Austria
Tel: +43 1 80100 0
E-Mail: hick at scigames.at

This communication (including any attachments) is intended for the use of the 
intended recipient(s) only and may contain information that is confidential, 
privileged or legally protected. Any unauthorized use or dissemination of this 
communication is strictly prohibited. If you have received this communication 
in error, please immediately notify the sender by return e-mail message and 
delete all copies of the original communication. Thank you for your cooperation.




[sqlite] Best way to handle time slicing of SQL data.

2015-06-02 Thread Hick Gunter
What is the reason for wanting the id of a record to be fixed at the unique 
record number of the original insertion?

Do you need to access historical data regularly or only for specific inquiries?

For rarely required historical data, you could use a "history table" to hold 
historic copies of records with fields valid_from and valid_to. Moving record 
contents to the history table should be doable via triggers, with the 
additional advantage that the rowid never needs to change.

For regular access to historic data, you would need to include valid_from and 
valid_to fields. These fields need to be present in every index and queried in 
every select.

-Urspr?ngliche Nachricht-
Von: Richard Warburton [mailto:richard at skagerraksoftware.com]
Gesendet: Dienstag, 02. Juni 2015 13:34
An: sqlite-users at mailinglists.sqlite.org
Betreff: [sqlite] Best way to handle time slicing of SQL data.

Hi,

I'm wanting to store data in a way such that I can choose a time in the past 
and view records as they were at that dateTime.  Therefore (in my mind), all 
updates are really inserts with a timestamp.  Ids are suddenly no longer 
primary keys, as many records can have the same id, but a new entry must be 
given a unique id (otherwise it will look like an update for an existing entry).

Here's a very simplified view of what I'm currently doing:
CREATE TABLE data (
UID INTEGER PRIMARY KEY AUTOINCREMENT,
Id INTEGER NOT NULL DEFAULT 0, -- shared by updates of the same data entry

Data TEXT,
User INT, -- who made this update
At INT, -- when the update was made
Remove INT NOT NULL DEFAULT 0 -- set to 1 if data entry has been deleted );

My initial questions are:
1) Do I need UID?  I'm currently using it to ensure a unique Id for when the 
user is creating a new entry.  This however means two operations, an Insert, 
then an Update to set the record's Id to match its UID. It also has the 
overhead of autoincrement, ensuring that UID is never ever reused and only goes 
upwards (I'm currently using MAX(UID)  to get the latest record <= the time I'm 
interested in.  I guess there's no extra storage as rowid would exist anyway.
2) Can I auto fill Id to UID on insert instead of having to do two operations?
3) Am I on track or is there a better way to approach this problem?

Thanks in advance for any feedback.

--
Richard Warburton
___
sqlite-users mailing list
sqlite-users at mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


___
 Gunter Hick
Software Engineer
Scientific Games International GmbH
FN 157284 a, HG Wien
Klitschgasse 2-4, A-1130 Vienna, Austria
Tel: +43 1 80100 0
E-Mail: hick at scigames.at

This communication (including any attachments) is intended for the use of the 
intended recipient(s) only and may contain information that is confidential, 
privileged or legally protected. Any unauthorized use or dissemination of this 
communication is strictly prohibited. If you have received this communication 
in error, please immediately notify the sender by return e-mail message and 
delete all copies of the original communication. Thank you for your cooperation.




[sqlite] Best way to handle time slicing of SQL data.

2015-06-02 Thread Stephen Chrzanowski
On Tue, Jun 2, 2015 at 7:34 AM, Richard Warburton <
richard at skagerraksoftware.com> wrote:

> 1) Do I need UID?  I'm currently using it to ensure a unique Id for when
> the user is creating a new entry.  This however means two operations, an
> Insert, then an Update to set the record's Id to match its UID. It also has
> the overhead of autoincrement, ensuring that UID is never ever reused and
> only goes upwards (I'm currently using MAX(UID)  to get the latest record
> <= the time I'm interested in.  I guess there's no extra storage as rowid
> would exist anyway.
>

This is basic Parent/Child relationship, or, One-To-Many relationships.
Your ID field can have many references to a parent table, so it is
absolutely 100% valid to have multiple IDs of the same value in one field,
but as I mention later, rather confusing to have multiple fields treated as
"primary information".

To answer your question for this particular example, no, you might not need
UID, but that'll depend on what you plan on doing with the information
you're inserting into this table.  If you plan on showing this record to
the user somehow, and they have the option to interact with the data
(Double-click to show more information on what was changed for this parent
record) then you'll need to provide your user interface with that UID.  In
Delphi/Pascal/Lazarus, every item within a list box or dropdown/combo box
contains an "object" pointer, which is just an integer.  I typically use
this "object" pointer to refer to whatever ID I pulled from the database
query when I'm populating the list.  If you're just displaying the data out
as a dump of text, then no, UID wouldn't be needed since you don't need to
go and reference that data back ever.

An example query to get the oldest record for a particular client would be

select * from data where ID=? order by At desc limit 1

In a multi-threaded/multi-client environment, I'd NEVER query against the
maximum identifier as that can change between the time you make the query
when when you actually want to do something with the result.  I want to
find the maximum value of relevant data I need, not something used
internally by the database to maintain referential integrity.  It "might"
BE the same result, but, at a code review, it doesn't LOOK like it is doing
the right thing.  Basically, your query doesn't tell the developer WHY
you're even making this query.

>From what I understand of your reasoning, you're "kind of" on the right
track.  You're looking to store historical record of changes on data for
any relevant child information to some sort of parent entity.  Say for
instance a change of address for a company or person, or recording the
change of the color of a car.  What you're missing out on is that your ID
field should already be known by the application to whatever the parent
record ID is, or in other words, your application should already know
you're changing the address of a particular person.  In this particular
table, you can probably keep the UID, but for all intents and purposes for
this example, if you ever make an update anything stored in this table,
your two relevant unique identifying keys would probably be the ID linking
to the parent record and the "At" field.  Unless the "At" value is being
changed/added multiple times in a second.


>
> 2) Can I auto fill Id to UID on insert instead of having to do two
> operations?
>

In my mind, having two "primary identifiers that mean two different things,
for one piece of information" indicates a bit more normalization needs to
happen.  Using cars as an example, it is confusing to say that that a
vehicle VIN contains information about the color of the car.  'Primary'
information should never be considered as something that can change later,
and, paint shops would be out of business in this particular scenario.  A
single vehicle has a single VIN, which has identifiable information that
CAN'T change at time of manufacturing, such as who made it, what location,
body trim, etc.  Sure, you can take every component from a Camaro SS and
put it  into the body of a Camaro LT, but, as far as the VIN for that LT is
concerned, it will be just an LT with SS parts.

The other thing is that, as I mentioned, you already should have ID
available when you're actually updating the record.  You shouldn't need to
have the application insert data, call the data back only to have to update
the record later.  In order to keep a paper trail on what has to be
changed, you obviously already know what is to be, or has changed, or what
new values are being entered into this table.  Even if you're adding a
brand new vehicle to the database, you need to add the VIN to a parent
table first and either get the LastID value after the insert, or retain the
VIN, then you add a new record to your "data" table referencing the ID
field to the VIN value.  If you're adding a new change record to the
vehicle (Brown paint to chrome paint anyone?) you already know the subjects
ID 

[sqlite] How to get length of all columns in a table

2015-06-02 Thread Richard Hipp
On 6/2/15, Igor Tandetnik  wrote:
> On 6/2/2015 2:28 AM, Hick Gunter wrote:
>> Sqlite3_column_bytes will convert numeric values to strings and return the
>> length of that "string representation" (excluding the terminating \0), not
>> the byte size required to store the numeric value itself.
>
> So will length() SQL function, I'm pretty sure.

Yes, both length() and sqlite3_column_bytes() will convert numbers to
strings before computing the length.  However, they are not
equivalent.

The length() SQL function returns the number of *characters*.  The
sqlite3_column_bytes() C function returns the number of *bytes*.

-- 
D. Richard Hipp
drh at sqlite.org


[sqlite] Best way to handle time slicing of SQL data.

2015-06-02 Thread Igor Tandetnik
On 6/2/2015 7:34 AM, Richard Warburton wrote:
> 2) Can I auto fill Id to UID on insert instead of having to do two
> operations?

Yes, with an AFTER INSERT trigger
-- 
Igor Tandetnik



[sqlite] How to get length of all columns in a table

2015-06-02 Thread Igor Tandetnik
On 6/2/2015 2:28 AM, Hick Gunter wrote:
> Sqlite3_column_bytes will convert numeric values to strings and return the 
> length of that "string representation" (excluding the terminating \0), not 
> the byte size required to store the numeric value itself.

So will length() SQL function, I'm pretty sure.
-- 
Igor Tandetnik



[sqlite] Best way to handle time slicing of SQL data.

2015-06-02 Thread J Decker
On Tue, Jun 2, 2015 at 4:34 AM, Richard Warburton <
richard at skagerraksoftware.com> wrote:

> Hi,
>
> I'm wanting to store data in a way such that I can choose a time in the
> past and view records as they were at that dateTime.  Therefore (in my
> mind), all updates are really inserts with a timestamp.  Ids are suddenly
> no longer primary keys, as many records can have the same id, but a new
> entry must be given a unique id (otherwise it will look like an update for
> an existing entry).
>
> Here's a very simplified view of what I'm currently doing:
> CREATE TABLE data (
> UID INTEGER PRIMARY KEY AUTOINCREMENT,
> Id INTEGER NOT NULL DEFAULT 0, -- shared by updates of the same data entry
>
> Data TEXT,
> User INT, -- who made this update
> At INT, -- when the update was made
> Remove INT NOT NULL DEFAULT 0 -- set to 1 if data entry has been deleted
> );
>
> My initial questions are:
> 1) Do I need UID?  I'm currently using it to ensure a unique Id for when
> the user is creating a new entry.  This however means two operations, an
> Insert, then an Update to set the record's Id to match its UID. It also has
> the overhead of autoincrement, ensuring that UID is never ever reused and
> only goes upwards (I'm currently using MAX(UID)  to get the latest record
> <= the time I'm interested in.  I guess there's no extra storage as rowid
> would exist anyway.
>

if Id == UID always; the question is really, do you need Id?


> 2) Can I auto fill Id to UID on insert instead of having to do two
> operations?
> 3) Am I on track or is there a better way to approach this problem?
>
> Using a GUID key can solve it also... but again if Id is always the same a
UID do you need Id?

Thanks in advance for any feedback.
>
> --
> Richard Warburton
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>


[sqlite] How to get length of all columns in a table

2015-06-02 Thread Hick Gunter
Sqlite3_column_bytes will convert numeric values to strings and return the 
length of that "string representation" (excluding the terminating \0), not the 
byte size required to store the numeric value itself.

-Urspr?ngliche Nachricht-
Von: J Decker [mailto:d3ck0r at gmail.com]
Gesendet: Montag, 01. Juni 2015 20:48
An: General Discussion of SQLite Database
Betreff: Re: [sqlite] How to get length of all columns in a table

you get the length in the result set?

sqlite3_column_bytes( statement, idx );

On Mon, Jun 1, 2015 at 10:28 AM, Drago, William @ CSG - NARDA-MITEQ < 
William.Drago at l-3com.com> wrote:

> > -Original Message-
> > From: sqlite-users-bounces at mailinglists.sqlite.org [mailto:sqlite-
> > users-bounces at mailinglists.sqlite.org] On Behalf Of Simon Slavin
> > Sent: Monday, June 01, 2015 12:59 PM
> > To: General Discussion of SQLite Database
> > Subject: Re: [sqlite] How to get length of all columns in a table
> >
> >
> > On 1 Jun 2015, at 4:45pm, Drago, William @ CSG - NARDA-MITEQ
> >  wrote:
> >
> > Just to confirm, the following is the only practical way to get the
> > length of each column in a table:
> > >
> > > Select Length(col_1)
> > > ,Length(col_2)
> > > ,Length(col_3)
> > > .
> > > .
> > > .
> > > ,Length(col_n)
> >
> > Martin's other answer will probably give you the answer faster:
> >
> > SELECT length(col_1||col2||col_3 ... col_n) FROM MyTable
>
> That returns the sum of the column lengths. I was looking for the
> length of each individual column.
>
> Thanks anyway,
>
> -Bill
> CONFIDENTIALITY, EXPORT CONTROL AND DISCLAIMER NOTE:This e-mail and
> any attachments are solely for the use of the addressee and may
> contain information that is privileged or confidential. Any
> disclosure, use or distribution of the information contained herein is
> prohibited. In the event this e-mail contains technical data within
> the definition of the International Traffic in Arms Regulations or
> Export Administration Regulations, it is subject to the export control
> laws of the U.S.Government. The recipient should check this e-mail and
> any attachments for the presence of viruses as L-3 does not accept any
> liability associated with the transmission of this e-mail. If you have
> received this communication in error, please notify the sender by
> reply e-mail and immediately delete this message and any attachments.
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>
___
sqlite-users mailing list
sqlite-users at mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


___
 Gunter Hick
Software Engineer
Scientific Games International GmbH
FN 157284 a, HG Wien
Klitschgasse 2-4, A-1130 Vienna, Austria
Tel: +43 1 80100 0
E-Mail: hick at scigames.at

This communication (including any attachments) is intended for the use of the 
intended recipient(s) only and may contain information that is confidential, 
privileged or legally protected. Any unauthorized use or dissemination of this 
communication is strictly prohibited. If you have received this communication 
in error, please immediately notify the sender by return e-mail message and 
delete all copies of the original communication. Thank you for your cooperation.