SQLite does not cast to integer - string

I've created the following select and calculate the "missing" value
select strftime('%d.%m. %H:%M', O_LROU_DEPARTDATE) || ' - ' || O_LROU_IDENT as Ident,
O_LROU_CSLCNTPICKED as 'done',
CAST((O_LROU_CSLCNT - O_LROU_CSLCNTPICKED) as integer) as 'missing'
from RAW_OM36
where (O_LROU_CSLCNT - O_LROU_CSLCNTPICKED) > 0
But the missing value is still a text and not a integer.
Here a picture! What's going wrong?

I have just had the same problem.
It is not clear from your picture how many records are selected. My driver determines the datatype from the first record. If the value in the first record is null then the driver interprets the column as string (32767). If the first record is a valid integer then the column is interpreted as integer.
A possible solution is to change
CAST((O_LROU_CSLCNT - O_LROU_CSLCNTPICKED) as integer)
to
IFNULL(O_LROU_CSLCNT - O_LROU_CSLCNTPICKED), 0)
accepting that changing nulls to zeros might not be acceptable to you application.

Related

Why I get error message "Invalid number" since UserID is NUMBER

I am little bit confusing and have no idea where I made mistake.
SELECT uta.StartDate, uta.EndDate FROM user_timesheets_absence uta
WHERE uta.UserID = 353
AND uta.Approved = 'true'
AND '2020-03-06' BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD') AND TO_DATE(uta.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY
In following query I get error
ORA-01722: invalid number
I try to understand where the error is, but when I realize query a deeper I can not see where the error is.
ABSENCETYPE VARCHAR2(255 CHAR)
ANSWER VARCHAR2(500 CHAR)
APPROVED NUMBER(10,0)
COMMENT_ CLOB
DAYS NUMBER(10,0)
ENDDATE VARCHAR2(50 CHAR)
ISANSWERED NUMBER(10,0)
ISREJECTED NUMBER(10,0)
STARTDATE VARCHAR2(50 CHAR)
USERABSENCEID NUMBER(10,0)
USERHASSEEN VARCHAR2(500 CHAR)
USERID NUMBER(10,0)
WIDTH NUMBER(10,0)
When I insert data into table, I use this kind of data and It works fine. But when I use SELECT statment I get error. I hope the error was UserID but it wasn't.
Insert into DB.USER_TIMESHEETS_ABSENCE (ABSENCETYPE,ANSWER,APPROVED,DAYS,ENDDATE,ISANSWERED,ISREJECTED,STARTDATE,USERABSENCEID,USERHASSEEN,USERID,WIDTH) values ('1','ne',0,8,'2020-02-06',1,1,'2020-01-30',89,'1',348,160);
Can someone tell me, where I made mistake ? What is wrong here ?
There is more than one problem in this query.
Firstly, here:
AND uta.Approved = 'true'
approved is a number, but you are comparing it against string 'true'. This does not work. Use a literal number on the right side of the equal sign.
Then, here:
AND '2020-03-06'
BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD')
AND TO_DATE(uta.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY
You are comparing a string against dates. This won't work. You probably want a literal date on the left side of between. I would also recommend using + 1 rather than the interval syntax, which should be reserved to timestamps:
AND DATE '2020-03-06'
BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD')
AND TO_DATE(uta.EndDate,'YYYY-MM-DD') + 1
Why are STARTDATE and ENDDATE defined as strings rather than date. Not using the correct data types is a surefire way to introduce data corruption issues. That's certainly where I would start looking.
The other thing is, always use explicit casting when converting strings into dates (or numbers) and vice versa. In this case you should use a date literal. Instead of
AND '2020-03-06' BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD') AND TO_DATE(uta.EndDate,'YYYY-MM-DD')
use
AND date '2020-03-06' BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD') AND TO_DATE(uta.EndDate,'YYYY-MM-DD')
If you have got data corruption in your date columns and you're on 12c or later you can use VALIDATE_CONVERSATION to filter rows which don't contain valid dates:
SELECT uta.StartDate, uta.EndDate FROM user_timesheets_absence uta
WHERE uta.UserID = 353
AND uta.Approved = 'true'
AND validate_conversion(uta.StartDate,'YYYY-MM-DD') = 1
AND validate_conversion(uta.EndDate,'YYYY-MM-DD') = 1
AND date '2020-03-06' BETWEEN TO_DATE(uta.StartDate,'YYYY-MM-DD') AND TO_DATE(uta.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY
You can also use this to find invalid date strings:
SELECT *
FROM user_timesheets_absence uta
WHERE validate_conversion(uta.StartDate,'YYYY-MM-DD') = 0
OR validate_conversion(uta.EndDate,'YYYY-MM-DD') = 0

Query a range in an Excel table linked to PowerApps Text Search box

First time asking a question here. As well as being pretty new to PowerApps as well.
I am trying to use two text input boxes for the user to define the min & max of their number range. basically i want the code to return all results that fall in the user defined range.
User inputs are:
SearchText.Text
MinSearch.Text and
MaxSearch.Text
PDFData is the table, and
RMANumber is the column that i want the Min & Max to search and return all within the user defined range. as of now, all i can get this to return are exact results, which just won't work for my situation. In my way of thinking, i want to add WHERE after the RAWidth and give greater or lesser arguments, but this isn't working for me. My full code is below, and any help is appreciated.
If(SearchText.Text="" && MinSearch.Text="" && MaxSearch.Text="", PDFData, Filter(PDFData,SearchText.Text in PDFAuthor|| SearchText.Text in PDFName|| SearchText.Text in RMANumber|| MinSearch.Text in RAWidth))
You can use the following expression for your query:
Filter(
PDFData,
SearchText.Text in PDFAuthor || SearchText.Text in PDFName,
Coalesce(Value(MinSearch.Text), -1) <= RAWidth,
Coalesce(Value(MaxSearch.Text), 1000000000) >= RAWidth)
If the SearchText is empty, then the conditions SearchText.Text in PDFAuthor and SearchText.Text in PDFName will both be true anyway, so there's no need for the If at that point.
For the other conditions, we can use the functions Value / Coalesce to convert the text input to a number; if the user didn't enter anything (or entered an invalid number), then the function Value will return a blank value, and the Coalesce function will use the next value. I'm using here -1 for the minumum value and 1000000000 for the maximum - if the possible range of values in your RAWidth column is between those numbers then you're fine.

SQLite - Left-pad zeros in returned Text field

I have a text field in my SQLite database that stores a Time value, but for unrelated reasons I can't change the data type to TIME.
The values are stored in HH:MM format, and I'm having trouble trying to sort results by time because the values below '10:00' are missing a leading zero. I would prefer not to store the data with leading zero for the same unrelated reasons.
I'd like to add something to the Query that would pad the missing character if necessary, causing the results to read '08:30' when collected. I've been searching through the command and function lexicon though and I'm not finding what I need.
Is there a simple way to do this inside a query?
Thanks
I think this would work:
select your_col, case when length(your_col) < 5
then '0' || your_col else your_col end from your_table
Demo using Python
>>> conn.execute('''select c, case when length(c) < 5
then '0' || c else c end from t''').fetchall()
[(u'10:00', u'10:00'), (u'8:00', u'08:00')]
SELECT REPLACE(PRINTF('%5s', your_col), ' ', '0') FROM your_table
The PRINTF call pads the value with spaces until it's 5 characters, and the
REPLACE call replaces those spaces with zeros.

Cognos query calculation - how to obtain a null/blank value?

I have a query calculation that should throw me either a value (if conditions are met) or a blank/null value.
The code is in the following form:
if([attribute] > 3)
then ('value')
else ('')
At the moment the only way I could find to obtain the result is the use of '' (i.e. an empty character string), but this a value as well, so when I subsequently count the number of distinct values in another query I struggle to get the correct number (the empty string should be removed from the count, if found).
I can get the result with the following code:
if (attribute='') in ([first_query].[attribute]))
then (count(distinct(attribute)-1)
else (count(distinct(attribute))
How to avoid the double calculation in all later queries involving the count of attribute?
I use this Cognos function:
nullif(1, 1)
I found out that this can be managed using the case when function:
case
when ([attribute] > 3)
then ('value')
end
The difference is that case when doesn't need to have all the possible options for Handling data, and if it founds a case that is not in the list it just returns a blank cell.
Perfect for what I needed (and not as well documented on the web as the opposite case, i.e. dealing with null cases that should be zero).

Replace empty strings with null values

I am rolling up a huge table by counts into a new table, where I want to change all the empty strings to NULL, and typecast some columns as well. I read through some of the posts and I could not find a query, which would let me do it across all the columns in a single query, without using multiple statements.
Let me know if it is possible for me to iterate across all columns and replace cells with empty strings with null.
Ref: How to convert empty spaces into null values, using SQL Server?
To my knowledge there is no built-in function to replace empty strings across all columns of a table. You can write a plpgsql function to take care of that.
The following function replaces empty strings in all basic character-type columns of a given table with NULL. You can then cast to integer if the remaining strings are valid number literals.
CREATE OR REPLACE FUNCTION f_empty_text_to_null(_tbl regclass, OUT updated_rows int)
LANGUAGE plpgsql AS
$func$
DECLARE
_typ CONSTANT regtype[] := '{text, bpchar, varchar}'; -- ARRAY of all basic character types
_sql text;
BEGIN
SELECT INTO _sql -- build SQL command
'UPDATE ' || _tbl
|| E'\nSET ' || string_agg(format('%1$s = NULLIF(%1$s, '''')', col), E'\n ,')
|| E'\nWHERE ' || string_agg(col || ' = ''''', ' OR ')
FROM (
SELECT quote_ident(attname) AS col
FROM pg_attribute
WHERE attrelid = _tbl -- valid, visible, legal table name
AND attnum >= 1 -- exclude tableoid & friends
AND NOT attisdropped -- exclude dropped columns
AND NOT attnotnull -- exclude columns defined NOT NULL!
AND atttypid = ANY(_typ) -- only character types
ORDER BY attnum
) sub;
-- RAISE NOTICE '%', _sql; -- test?
-- Execute
IF _sql IS NULL THEN
updated_rows := 0; -- nothing to update
ELSE
EXECUTE _sql;
GET DIAGNOSTICS updated_rows = ROW_COUNT; -- Report number of affected rows
END IF;
END
$func$;
Call:
SELECT f_empty2null('mytable');
SELECT f_empty2null('myschema.mytable');
To also get the column name updated_rows:
SELECT * FROM f_empty2null('mytable');
db<>fiddle here
Old sqlfiddle
Major points
Table name has to be valid and visible and the calling user must have all necessary privileges. If any of these conditions are not met, the function will do nothing - i.e. nothing can be destroyed, either. I cast to the object identifier type regclass to make sure of it.
The table name can be supplied as is ('mytable'), then the search_path decides. Or schema-qualified to pick a certain schema ('myschema.mytable').
Query the system catalog to get all (character-type) columns of the table. The provided function uses these basic character types: text, bpchar, varchar, "char". Only relevant columns are processed.
Use quote_ident() or format() to sanitize column names and safeguard against SQLi.
The updated version uses the basic SQL aggregate function string_agg() to build the command string without looping, which is simpler and faster. And more elegant. :)
Has to use dynamic SQL with EXECUTE.
The updated version excludes columns defined NOT NULL and only updates each row once in a single statement, which is much faster for tables with multiple character-type columns.
Should work with any modern version of PostgreSQL. Tested with Postgres 9.1, 9.3, 9.5 and 13.

Resources