Parametric recursive looped SQLite insert - do all columns have to be supplied? - sqlite

I added a new column to my table, so there are now 4 instead of 3, and am now getting the following error when do a parametric insert (looped):
table 'test' has 4 columns but 3 values were supplied
Does this mean that you have to code your query for EVERY column the table has (as opposed to just the columns you want populated) when doing inserts, and that SQLite won't just add a default value if a column is missing from the query?
My query is:
"INSERT OR IGNORE INTO test VALUES (NULL, #col2, #col3)"
And this is the code that controls what's inserted in the recursive lopp:
sqlStatement.clearParameters();
var _currentRow:Object = _dataArray.shift();
sqlStatement.parameters["#col2"] = _currentRow.val2;
sqlStatement.parameters["#col3"] = _currentRow.val3;
sqlStatement.execute();
Ideally, I'd like column 4 to be left blank, without having to code it into the query.
Thanks for taking a look.

If you're inserting less values than there are columns, you need to explicitly specify the columns you are inserting to. For example
INSERT INTO test(firstcolumn,secondcolumn) VALUES(1,2);
Those columns that are not specified will get the default value, or NULL if there is no default value.

Related

Can we reduce column size filled with records

Can we decrease a size of a column? Suppose there is table A having column size 10. After inserting the data in the table, I want to reduce the size of the column. Can we reduce it?
Create table A
(Emp varchar2(10));
Insert into A values ('Ana');
Alter table A modify (varchar2(5));
Yes you can. An error will be thrown if the existing values have a larger size than the new datatype. See below.
koen>create table things (name VARCHAR2(100));
Table THINGS created.
koen>insert into things(name) values ('Car');
1 row inserted.
koen>alter table things modify name VARCHAR2(5);
Table THINGS altered.
koen>alter table things modify name VARCHAR2(2);
Error starting at line : 1 in command -
alter table things modify name VARCHAR2(2)
Error report -
ORA-01441: cannot decrease column length because some value is too big
01441. 00000 - "cannot decrease column length because some value is too big"
*Cause:
*Action:
koen>

Issue with replacing NULL sqlite3 database column values with other types in Python 3?

I've run into a problem with the sqlite3 module in Python 3, where I can't seem to figure out how to replace NULL values from the database with other ones, mainly strings and integers.
This command doesn't do the job, but also raises no exceptions:
UPDATE table SET animal='cat' WHERE animal=NULL AND id=32
The database table column "animal" is of type TEXT and gets filled with NULLs where no other value has been specified.
The column "id" is primary keyed and thus features only unique integer row indices.
If the column "animal" is defined, not NULL, the above command works flawlessly.
I can replace existing strings, integers, and floats with it.
What am I overlooking here?
Thanks.
The NULL value in SQL is special, and to compare values against it you need to use the IS and IS NOT operators. So your query should be this:
UPDATE table
SET animal = 'cat'
WHERE animal IS NULL AND id = 32;
NULL by definition means "unknown" in SQL, and so comparing a column directly against it with = also produces an unknown result.

Increase int value in null column

I made a stupid mistake and created a column like this:
CREATE TABLE mytable (mycol INTEGER, ...)
As you can see, I forgot to define a default value like "DEFAULT 0".
In my code, I need to raise the value in "mycol" by 1.
I was baffled when I found out that this code didn't have any effect.
UPDATE mytable SET mycol=(mycol+1)
The column value stays as it is. In my case "EMPTY" (=no value at all).
I would like to avoid re-creating the table if possible.
I would like to ask if there is any easy way to fix this in the SQL statement so that an EMPTY value is seen as 0 so that
UPDATE mytable SET mycol=(mycol+1)
on a column value of EMPTY would finally produce the new column value of 1.
You can use such as below if your column has null value:
UPDATE mytable SET mycol= ifnull(mycol,0)+1

Merging two tables and returning value through r script

I am attempting to add a dynamic column to a table in spotfire that is updated using r-script/data functions in order to handle different variable types. When you just insert columns, it does not allow you to change the column from a text value to a string value.
The basic code structure is create a new table by merging the base table with the information table, select a column header to populate the new column from, and return the calculated column values to the base table. Parameters are as follows:
Input Parameters:
Name Type
columnMatch Value
baseTable Table
infoTable Table
Output Parameters (to be added to baseTable)
Name Type
outputColumn Column
Script
newTable <- merge(baseTable,infoTable, by = "uniqueIdentifier")
cnames <- colnames(newTable)
outputColumn <- newTable[,match(colorSelection, cnames, nomatch=1)]
outputColumn
The issue thatI am having is as follows:
The code is not returning the correct value for the correct uniqueIdentifier. Is there a way that I can make the values line up, or sort the table in order to return the correct value for the correct uniqueIdentifier?
Thanks!
Jordan
EDIT: found out how to dynamically refer to column number using match function.

SUM totals by FOR ALL ENTRIES itab keys

I want to execute a SELECT query on a database table that has 6 key fields, let's assume they are keyA, keyB, ..., keyF.
As input parameters to my ABAP function module I do receive an internal table with exactly that structure of the key fields, each entry in that internal table therefore corresponds to one tuple in the database table.
Thus I simply need to select all tuples from the database table that correspond to the entries in my internal table.
Furthermore, I want to aggregate an amount column in that database table in exactly the same query.
In pseudo SQL the query would look as follows:
SELECT SUM(amount) FROM table WHERE (keyA, keyB, keyC, keyD, keyE, keyF) IN {internal table}.
However, this representation is not possible in ABAP OpenSQL.
Only one column (such as keyA) is allowed to state, not a composite key. Furthermore I can only use 'selection tables' (those with SIGN, OPTIOn, LOW, HIGH) after they keyword IN.
Using FOR ALL ENTRIES seems feasible, however in this case I cannot use SUM since aggregation is not allowed in the same query.
Any suggestions?
For selecting records for each entry of an internal table, normally the for all entries idiom in ABAP Open SQL is your friend. In your case, you have the additional requirement to aggregate a sum. Unfortunately, the result set of a SELECT statement that works with for all entries is not allowed to use aggregate functions. In my eyes, the best way in this case is to compute the sum from the result set in the ABAP layer. The following example works in my system (note in passing: using the new ABAP language features that came with 7.40, you could considerably shorten the whole code).
report zz_ztmp_test.
start-of-selection.
perform test.
* Database table ZTMP_TEST :
* ID - key field - type CHAR10
* VALUE - no key field - type INT4
* Content: 'A' 10, 'B' 20, 'C' 30, 'D' 40, 'E' 50
types: ty_entries type standard table of ztmp_test.
* ---
form test.
data: lv_sum type i,
lt_result type ty_entries,
lt_keys type ty_entries.
perform fill_keys changing lt_keys.
if lt_keys is not initial.
select * into table lt_result
from ztmp_test
for all entries in lt_keys
where id = lt_keys-id.
endif.
perform get_sum using lt_result
changing lv_sum.
write: / lv_sum.
endform.
form fill_keys changing ct_keys type ty_entries.
append :
'A' to ct_keys,
'C' to ct_keys,
'E' to ct_keys.
endform.
form get_sum using it_entries type ty_entries
changing value(ev_sum) type i.
field-symbols: <ls_test> type ztmp_test.
clear ev_sum.
loop at it_entries assigning <ls_test>.
add <ls_test>-value to ev_sum.
endloop.
endform.
I would use FOR ALL ENTRIES to fetch all the related rows, then LOOP round the resulting table and add up the relevant field into a total. If you have ABAP 740 or later, you can use REDUCE operator to avoid having to loop round the table manually:
DATA(total) = REDUCE i( INIT sum = 0
FOR wa IN itab NEXT sum = sum + wa-field ).
One possible approach is simultaneous summarizing inside SELECT loop using statement SELECT...ENDSELECT statement.
Sample with calculating all order lines/quantities for the plant:
TYPES: BEGIN OF ls_collect,
werks TYPE t001w-werks,
menge TYPE ekpo-menge,
END OF ls_collect.
DATA: lt_collect TYPE TABLE OF ls_collect.
SELECT werks UP TO 100 ROWS
FROM t001w
INTO TABLE #DATA(lt_werks).
SELECT werks, menge
FROM ekpo
INTO #DATA(order)
FOR ALL ENTRIES IN #lt_werks
WHERE werks = #lt_werks-werks.
COLLECT order INTO lt_collect.
ENDSELECT.
The sample has no business sense and placed here just for educational purpose.
Another more robust and modern approach is CTE (Common Table Expressions) available since ABAP 751 version. This technique is specially intended among others for total/subtotal tasks:
WITH
+plants AS (
SELECT werks UP TO 100 ROWS
FROM t011w ),
+orders_by_plant AS (
SELECT SUM( menge )
FROM ekpo AS e
INNER JOIN +plants AS m
ON e~werks = m~werks
GROUP BY werks )
SELECT werks, menge
FROM +orders_by_plant
INTO TABLE #DATA(lt_sums)
ORDER BY werks.
cl_demo_output=>display( lt_sums ).
The first table expression +material is your internal table, the second +orders_by_mat quantities totals selected by the above materials and the last query is the final output query.

Resources