SQLite3 can't do addition in WHERE clause? - sqlite

I have the following simple query that I execute on a SQLite3 database:
SELECT AField,AnotherField FROM ATable WHERE AnIntField>strftime('%s');
This works fine and returns the expected result.
If I perform the slightly modified query:
SELECT AField,AnotherField FROM ATable WHERE AnIntField+86400>strftime('%s');
Then I don't get any results! This doesn't make any sense! I have tried putting brackets around AnIntField+86400 but that doesn't help. And yes, the values of AnIntField are sufficiently larger than strftime('%s') that it won't return different results.
Is there any reason for this behaviour?

This is a total guess but what happens if you wrap AnIntField+86400 in the SQLite3 equivalent of a cast ?
In TSQL you'd do something like this:
WHERE CAST(AnIntField + 86400 AS int) > strftime('%s')
My thought is that the AnIntField+val is coming out as an append rather than addition.
Actually, if cast doesn't work, try changing select to
SELECT AnIntField+86400 FROM ...
And see what it spits out.

Related

I keep getting a syntax error on this code [duplicate]

I'm trying to insert some information to MySQL with Pascal, but when I run the program I get the error
unknown column 'mohsen' in field list
This is my code
procedure TForm1.Button1Click(Sender: TObject);
var
aSQLText: string;
aSQLCommand: string;
namee:string;
family:string;
begin
namee:='mohsen';
family:='dolatshah';
aSQLText:= 'INSERT INTO b_tbl(Name,Family) VALUES (%s,%s)';
aSQLCommand := Format(aSQLText, [namee, family]);
SQLConnector1.ExecuteDirect(aSQLCommand);
SQLTransaction1.Commit;
end;
How can I solve this problem?
It's because your
VALUES (%s,%s)
isn't surrounding the namee and family variable contents by quotes. Therefore, your back-end Sql engine thinks your mohsen is a column name, not a value.
Instead, use, e.g.
VALUES (''%s'',''%s'')
as in
Namee := 'mohsen';
Family := 'dolatshah';
aSQLText:= 'INSERT INTO b_tbl(Name,Family) VALUES (''%s'',''%s'')';
aSQLCommand := Format(aSQLText,[namee,family]);
In the original version of my answer, I explained how to fix your problem by "doubling up" single quotes in the Sql you were trying to build, because it seemed to me that you were having difficulty seeing (literally) what was wrong with what you were doing.
An alternative (and better) way to avoid your problem (and the one I always use in real life) is to use the QuotedStr() function. The same code would then become
aSQLText := 'INSERT INTO b_tbl (Name, Family) VALUES (%s, %s)';
aSQLCommand := Format(aSQLText, [QuotedStr(namee), QuotedStr(family)]);
According to the Online Help:
Use QuotedStr to convert the string S to a quoted string. A single quote character (') >is inserted at the beginning and end of S, and each single quote character in the string is >repeated.
What it means by "repeated" is what I've referred to as "doubling up". Why that's important, and the main reason I use QuotedStr is to avoid the Sql db-engine throwing an error when the value you want to send contains a single quote character as in O'Reilly.
Try adding a row containing that name to your table using MySql Workbench and you'll see what I mean.
So, not only does using QuotedStr make constructing SQL statements as strings in Delphi code less error-prone, but it also avoid problems at the back-end, too.
Just in case this will help anybody else I had the same error when I was parsing a python variable with a sql statement and it had an if statement in i.e.
sql="select bob,steve, if(steve>50,'y','n') from table;"
try as I might it coming up with this "unknown column y" - so I tried everything and then I was about to get rid of it and give it up as a bad job until I thought I would swap the " for ' and ' for "..... Hoooraaahh it works!
This is the statement that worked
sql='select bob,steve, if(steve>50,"y","n") from table;'
Hope it helps...
To avoid this sort of problem and SQL injection you should really look into using SQL parameters for this, not the Pascal format statement.

RODBC gives proper row count but yields empty query

Using R-3.5.0 and RODBC v. 1.3-15 on Windows.
I am trying to query data from a remote database. I can connect fine and if I do a query to count the rows, the answer comes out correctly. But if I try to remove the count statement select count(*) and actually get the data via select *, I yield an empty query (with some rather strange headers). Only two of the column names come out correctly and the rest are question marks and a number (as shown below). I can using sql developer to query the data no problem.
I include the simplest version of the code below but I get the same results if I try to limit to just a few rows or certain conditions, etc. Sorry I cannot create a reproducible example but as this is a remote db and I have no idea what the problem is, I'm not sure how I could even do that.
I can query other tables from different schemas within the same odbc connection, so I don't think it is that. I have tried with and without the believeNRows and the rows_at_time.
Thank you for any thoughts.
channel <- odbcConnect("mydb", uid="myuser", pwd="mypass", believeNRows=FALSE,rows_at_time = 1)
myquery <- paste("select count(*) from MYSCHEMA.MYTABLE")
sqlQuery(channel, myquery)
COUNT(*)
1 149712361
myquery <- paste("select * from MYSCHEMA.MYTABLE")
sqlQuery(channel, myquery)
[1] ID FMC_IN_ID ? ?.1 ?.2 ?.3 ?.4 ?.5 ?.6 ?.7 ?.8 ?.9 ?.10 ?.11 ?.12 ?.13 ?.14 ?.15
<0 rows> (or 0-length row.names)
I would try the following:
add a simple limit 100 to your query to see if you can get some data back
add the believeNRows option to the sqlQuery call -- in my experience it is needed at that level
In case it helps others, the problem was that the database contained an Oracle spatial field (MDSYS.SDO_GEOMETRY). R did not know what to do with it. I assumed it would just convert it to a character but instead it just got confused. By omitting the spatial field, the query worked fine.

AssertResultSetsHaveSameMetaData in TSQLT

I am using TSQLT AssertResultSetsHaveSameMetaData to compare metadata between two tables.But the problem is that i cannot hardcode the table name since i am passing the table name as the parameter at the runtime.So is there any way to do that
You use tSQLt.AssertResultSetsHaveSameMetaData by passing two select statements like this:
exec tSQLt.AssertResultSetsHaveSameMetaData
'SELECT TOP 1 * FROM mySchema.ThisTable;'
, 'SELECT TOP 1 * FROM mySchema.ThatTable;';
So it should be quite easy to parameterise the names of the tables you are comparing and build the SELECT statements based on those table name parameters.
However, if you are using the latest version of tSQLt you can also now use tSQLt.AssertEqualsTableSchema to do the same thing. You would use this assertion like this:
exec tSQLt.AssertEqualsTableSchema
'mySchema.ThisTable'
, 'mySchema.ThatTable';
Once again, parameterising the tables names would be easy since they are passed to AssertEqualsTableSchema as parameters.
If you explain the use case/context and provide sample code to explain what you are trying to do you stand a better chance of getting the help you need.

how the utl_raw.cast_to_varchar2(NLSSORT(')) works

why this query not giving any records. Please guide me
SELECT *
FROM DUAL
WHERE utl_raw.cast_to_varchar2(NLSSORT('sravanth','nls_sort=binary_ai'))
LIKE utl_raw.cast_to_varchar2(NLSSORT('sravan','nls_sort=binary_ai'))|| '%'
The reason this is not working in obvious when displaying the output of NLSSORT :
SELECT NLSSORT('sravanth','nls_sort=binary_ai') FROM DUAL
UNION ALL
SELECT NLSSORT('sravan','nls_sort=binary_ai') FROM DUAL
NLSSORT('SRAVANTH','NLS_SORT=BINARY_AI')
73726176616E746800
73726176616E00
^^
Please note that NLSSORT add an extra NUL char at the end of the string. This is not specified in the documentation -- and you shouldn't probably assume it will be always behave the same. Anyway, if you really want to use NLSSORT that way, you will have to handle the extra byte by hand. See https://stackoverflow.com/a/20490866/2363712 as an example.

Extract first word in a SQLite3 database

I have a SQLITE3 database wherein I have stored various columns. One column (cmd) in particular contains the full command line and associated parameters. Is there a way to extract just the first word in this column (just before the first space)? I am not interested in seeing the various parameters used, but do want to see the command issued.
Here's an example:
select cmd from log2 limit 3;
user-sync //depot/PATH/interface.h
user-info
user-changes -s submitted //depot/PATH/build/...#2011/12/06:18:31:10,#2012/01/18:00:05:55
From the result above, I'd like to use an inline SQL function (if available in SQLITE3) to parse on the first instance of space, and perhaps use a left function call (I know this is not available in SQLITE3) to return just the "user-sync" string. Same for "user-info" and "user-changes".
Any ideas?
Thanks.
My soluion:
sqlite> CREATE TABLE command (cmd TEXT);
sqlite> INSERT INTO command (cmd) VALUES ('ls'),('cd ~'),(' mpv movie.mkv ');
sqlite> SELECT substr(trim(cmd),1,instr(trim(cmd)||' ',' ')-1) FROM command;
ls
cd
mpv
Pros:
it's not that a dirty hack
it only uses core functions
"Finds the first occurrence" function is one of the SQLite3 Core Functions (http://www.sqlite.org/lang_corefunc.html).
Of course, it is much better to use instr(X,Y).
So you can write:
SELECT substr(cmd,1,instr(cmd,' ')-1) FROM log2
As the position of your first space character is unknown, I don't think there is a corefunction in SQLite that will help.
I think you'll have to create one http://www.sqlite.org/c3ref/create_function.html
Here's a hack
sqlite> create table test (a);
sqlite> insert into test values ("This is a test.");
sqlite> select * from test;
This is a test.
sqlite> select rtrim(substr(replace(a,' ','----------------------------------------------------------------------------------------'),1,80),'-') from test;
This
It works as long as your longest command is less than 80 characters (and you include 80 '-' characters in the substitution string -- I didn't count them!). If your commands can contain '-' just use a different character that is not allowed in the commands.
I don't believe that's something you'll be able to do within the SQL itself. SQLite's support for string handling functions is not as extensive as other RDBMSs (some of which would let you do a SUBSTR with a Reg Exp).
My suggestion is either to write your own SQL function as suggested by #Jon or just do it as a post-processing step in your app code.

Resources