Let's suppose we have a table defined with:
CREATE TABLE IF NOT EXISTS signals(sigid INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)
This table initially is empty.
I would like to get the sigid for a given name with a select and in case name does not exist, add it and get the new autoincremented id.
I would like to use this query in order to autogenerate ,when needed, a new id that is used as foreign key in another table. I must put attention to the performances so I cannot proceed as :
check if name is present and return id witha a SELECT
if returned id is null create a new entry with an INSERT
get the new id again with a new SELECT
Is it possible do it with a single SELECT-like query ?
Thanks!
i think with an single select no.
Let's say i want to insert id_build = 3, hashed_value = 1 into the big table 'crash'.
The code in example makes first select to check if the value was already in the table, if yes skips the insert with where .. is null then retrive the id from already saved into temporary table.
example :
create temporary table if not exists Variablez(Name TEXT primary key on conflict replace, Value TEXT); --storing vars
insert into Variablez(Name, Value) values ('tmp_id', (select id_crash from crash where hashed_value = "1" )); --put id if was existing
insert into crash(id_build, hashed_value) select 3, 1 where (select Value from Variablez where Name = 'tmp_id' ) is null; -- insert if not exists
select
case
when (select Value from Variablez where name = 'tmp_id' ) is null then
'0'
else
'1'
end
as existing,
case
when (select Value from Variablez where name = 'tmp_id' ) is null then
(select id_crash from crash where hashed_value = "1")
else
(select Value from Variablez where name = 'tmp_id')
end
as id_returned;
if the table is empty and you are the one filling it in just one shot (and you don't need to do it again later on when there is data in the table), AND you don't have too many rows, then you could just cache the names you have already inserted and look them up in memory.
It's more of a comment, I guess.
there is also this for getting the last inserted id:
SELECT last_insert_rowid();
But if the above applies, you are even faster by assigning the ids yourself, and not define it as AUTOINCREMENT. Then you don't need to get the last inserted id, you just keep a counter and all the names inserted and increment for each new name you find.
CREATE TABLE IF NOT EXISTS signals(sigid INTEGER PRIMARY KEY NOT NULL, name TEXT)
List<String> insertedNames = new List<String>();
int count = 0;
while(input.hasNext())
{
String name = input.next();
if( !insertedNames.contains(name) )
{
var sql = "insert into table (sigid,name) VALUES (" + count + ", " + name + ")";
executeSql(sql);
insertedNames.add(name);
count++;
}
}
answering your comment
public int getId( string name )
{
String sql = "select id from table where name='" + name + "'";
int theIdForTheName = executeAndGetFirstColumnAsInt(sql);
return theIdForTheName;
}
i don't know what else to tell you...
Related
I have a historic table that won't be updated with new inserts, and a have a view that everyday will be update with new inserts. So I need to know if my SQL is correct.
This SQL needs to get all entries that inside in FATO_Proposta_Planilha table (Table 1)
and to add the entries not similar that are in the FATO_Proposta_View table (Table 2).
So, this SQL must have all entries from Table 1 more all entries from Table 2 that are not repeated in the Table 1. Can you give a opinion about this SQL, please?
SELECT vw.[DescPac] [PA]
,vw.[DescRegional] [Regional]
,vw.[DescSuperintendencia] [Superintendencia]
,vw.[NUM_CPF_CNPJ] [Documento_Numero]
,pla.[Nome] [Nome]
,pla.[Produto] [Produto]
,pla.[Modalidade] [Modalidade]
,vw.[NUM_CONTRATO_CREDITO] [Contrato]
,vw.[DESC_FINALIDADE_OPCRED] [Finalidade]
,vw.[DATA_OPERACAO] [Data_operacao]
,pla.[Data_mov_entrada] [Data_mov_entrada]
,vw.[DATA_VENC_OPCRED] [Data_vencimento]
,vw.[VALOR_CONTRATO_OPCRED] [Valor_contrato]
,pla.[Processo_Lecon] [Processo_Lecon]
,CASE WHEN ISNULL(pla.Origem, '') = ''
THEN 'Esteira Convencional'
ELSE pla.Origem
END [Origem]
FROM Proposta_View vw
LEFT JOIN FATO_Proposta_Planilha pla
ON vw.NUM_CONTRATO_CREDITO = pla.Contrato
UNION
SELECT [PA] [PA]
,[Regional] [Regional]
,[Superintendencia] [Superintendencia]
,[Documento_Numero] [Documento_Numero]
,[Nome] [Nome]
,[Produto] [Produto]
,[Modalidade] [Modalidade]
,[Contrato] [Contrato]
,[Finalidade] [Finalidade]
,[Data_operacao] [Data_operacao]
,[Data_mov_entrada] [Data_mov_entrada]
,[Data_vencimento] [Data_vencimento]
,[Valor_contrato] [Valor_contrato]
,[Processo_Lecon] [Processo_Lecon]
,CASE WHEN ISNULL(Origem, '') = ''
THEN 'Esteira Convencional'
ELSE Origem
END [Origem]
If you are only inserting rows through the view you can add an extra column with a DEFAULT value to distinguish the old rows from the new ones.
For example if you have a table t as:
create table t (a int primary key not null);
insert into t (a) values (123), (456);
You can add the extra column as:
alter table t add is_new int default 1;
update t set is_new = 0;
create view v as select a from t;
Then each insert through the view won't see that new column and will insert with value 1.
insert into v (a) values (789), (444);
Then it's easy to find the new rows:
select * from t where is_new = 1;
Result:
a is_new
---- ------
444 1
789 1
Se running example at db<>fiddle.
here is my table
my error seems to show that when I am trying to run the insert eloquent, the both my id columns
give out a null value, this the issue:
SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column "id" of relation "hms_bbr_category" violates not-null constraint DETAIL: Failing row contains (null, null, Insert 1, Insert Desc, null, null, null, null, null, null, null, null, null, null). (SQL: insert into "hms_bbr_category" ("category_name", "category_description") values (Insert 1, Insert Desc) returning "id")
Model: HmsBbrCategory
class HmsBbrCategory extends Model
{
protected $table = 'hms_bbr_category';
protected $primaryKey = 'id';
public $timestamps = false;
}
Routes:
Route::get('/bbr-category-configuration', function(){
$addCategory = new App\Models\HmsBbrCategory;
$addCategory->category_name='Insert 1';
$addCategory->category_description='Insert Desc';
$addCategory->save();
});
Note that I am strting it out simple at first, where the insert triggers when a route link is clicked.
I tried manually inserting an increment option, but it still seems to be not working properly.
$addCategory = id->id + 1;
$addCategory = category_id->category_id + 1;
Thanks for any help, feel free to tell me to elaborate if the question still needs clarification
Update
just to note, I did not create this with migration, this table as given to me as it is, no changes are allowed.
updated my insert with columns containing "NOT NULL" but im getting another error:
$addCategory = new App\Models\HmsBbrCategory;
$addCategory = id->id + 1;
$addCategory = category_id->category_id + 1;
$addCategory->category_name='Insert 1';
$addCategory->category_description='Insert Desc';
$addCategory->created_by='Me';
$addCategory->category_description=CURRENT_TIMESTAMP;
$addCategory->save();
error:
Symfony\Component\Debug\Exception\FatalThrowableError
syntax error, unexpected '->' (T_OBJECT_OPERATOR)
per your table structure , these columns can't be null and have no default value :
category_id
created_by
created_datetime
so when you insert / update , these columns can't stay null.
so in your code , you are not providing any of those values.
also "id->id + 1" is wrong , because you don''t have a variable called id , and even if you had , not sure what does "id + 1" supposed to give your PK in table.
however id has a default value and seems like it gets nextval() , so you are good there.
but for category_id , you need to pass an integer id , if you want to get the last category_id in the table and add 1 as a new one , this is not how you can do it.
I have the following table:
CREATE TABLE tab (
id SERIAL PRIMARY KEY,
code TEXT NOT NULL,
data TEXT
)
In some cases, I'd like to insert a new row ensuring that the code column is generated by the id column. In other cases the code is provided by the user.
For example:
INSERT INTO tab(code, data) VALUES ('code: ' || id::TEXT, 'my data');
The expected result is something like:
id
code
data
1
code: 1
abc
2
code: 2
xyz
INSERT INTO tab(code, data) VALUES ('user.provided.code', 'my data');
The expected result is something like:
id
code
data
1
code: 1
abc
2
code: 2
xyz
3
user.provided.code
xyz
Is it possibile in one statement?
It sounds like you want to default the coder to something based on the id. Unfortunately, this doesn't work in Postgres:
create table tab (
id integer primary key generated always as identity,
code text not null default ('code '||id::text),
data text
);
One option is a single statement that does both an insert and update:
with i as (
insert into tab (code, data)
values ('', 'my data'
returning *
)
update tab
set code = 'code: ' || id::TEXT
where tab.id in (select i.id from i);
Another is to use a trigger that assigns the value.
Use INSERT INTO .. SELECT as follows:
INSERT INTO tab(code, data)
select 'code: ' || id::TEXT, 'my data' from tab;
Note: In newly added data(above insert), you are missing to add id column data or I think it is auto generated.
When selecting timestamps (which are nullable with defualt null) from a source table through a PHP script and trying to insert into an identical destination table,
I get the error 'SYNTAX of date, time or timestamp value not valid SQL state 22008'. I believe it's because some source records are null. When the script runs, I get about half the records inserted into my destination table successfully but only the ones that have actual timestamp values. The null records haven't been inserted.
My statements:
SELECT
TIMESTAMP_EXPIRATION
FROM TABLE1;
INSERT INTO TABLE2 (EXPIRATION_T)
VALUES ($TIMESTAMP_EXPIRATION);
The problem is that half of my source records are null and the other half are TIMESTAMP with a degree of 6
The definition of source and destination tables have the column as 'TIMESTAMP_EXPIRATION FOR COLUMN 0011TTT TIMESTAMP DEFAULT NULL' and 'EXPIRATION_T FOR COLUMN 00EETTT TIMESTAMP DEFAULT NULL'
WHat can I do to get the null values to insert as well?
UPDATE: CREATION STATEMENTS
CREATE TABLE TABLE1 (
ID INTEGER GENERATED ALWAYS AS IDENTITY (
START WITH 1 INCREMENT BY 1 ),
TIMESTAMP_EXPIRATION FOR COLUMN 0011TTT TIMESTAMP DEFAULT NULL )
RCDFMT TABLE1 ;
CREATE TABLE TABLE2 (
ID INTEGER GENERATED ALWAYS AS IDENTITY (
START WITH 1 INCREMENT BY 1 ),
EXPIRATION_T} FOR COLUMN 00EETTT TIMESTAMP DEFAULT NULL )
RCDFMT TABLE2 ;
UPDATE: PHP SCRIPT
$getDev = "
SELECT
ID,
TIMESTAMP_EXPIRATION
FROM TABLE1
";
$stmt = odbc_exec($DB2connDEV, $getDev);
while($gettingItems = odbc_fetch_array($stmt)){
$rows[] = $gettingItems;
}
foreach($rows as $row){
$originalID = $row['ID'];
$expiration = $row['TIMESTAMP_EXPIRATION'];
$insertTable = "INSERT INTO table2 (id,expiration_t) VALUES (
$originalID,
'$expiration')";
$stmt = odbc_exec($DB2connPROD, $insertTable);
}
Consider parameterization with a prepared statement and not string interpolation such as this '$expiration' that renders null to empty string:
$apn_stmt = odbc_prepare($DB2connPROD, "INSERT INTO table2 (id, expiration_t) VALUES (?, ?)");
$sel_stmt = odbc_exec($DB2connDEV, "SELECT ID, TIMESTAMP_EXPIRATION FROM TABLE1");
while($gettingItems = odbc_fetch_array($sel_stmt)) {
$rows[] = $gettingItems;
}
foreach($rows as $row) {
$originalID = $row['ID'];
$expiration = ($row['TIMESTAMP_EXPIRATION'] == '' ? NULL : $row['TIMESTAMP_EXPIRATION']);
$insertTable = odbc_execute($apn_stmt, array($originalID, $expiration));
}
I want to declare a variable in SQLite and use it in insert operation.
Like in MS SQL:
declare #name as varchar(10)
set name = 'name'
select * from table where name = #name
For example, I will need to get last_insert_row and use it in insert.
I have found something about binding but I didn't really fully understood it.
SQLite doesn't support native variable syntax, but you can achieve virtually the same using an in-memory temp table.
I've used the below approach for large projects and works like a charm.
/* Create in-memory temp table for variables */
BEGIN;
PRAGMA temp_store = 2; /* 2 means use in-memory */
CREATE TEMP TABLE _Variables(Name TEXT PRIMARY KEY, RealValue REAL, IntegerValue INTEGER, BlobValue BLOB, TextValue TEXT);
/* Declaring a variable */
INSERT INTO _Variables (Name) VALUES ('VariableName');
/* Assigning a variable (pick the right storage class) */
UPDATE _Variables SET IntegerValue = ... WHERE Name = 'VariableName';
/* Getting variable value (use within expression) */
... (SELECT coalesce(RealValue, IntegerValue, BlobValue, TextValue) FROM _Variables WHERE Name = 'VariableName' LIMIT 1) ...
DROP TABLE _Variables;
END;
For a read-only variable (that is, a constant value set once and used anywhere in the query), use a Common Table Expression (CTE).
WITH const AS (SELECT 'name' AS name, 10 AS more)
SELECT table.cost, (table.cost + const.more) AS newCost
FROM table, const
WHERE table.name = const.name
SQLite WITH clause
Herman's solution works, but it can be simplified because Sqlite allows to store any value type on any field.
Here is a simpler version that uses one Value field declared as TEXT to store any value:
CREATE TEMP TABLE IF NOT EXISTS Variables (Name TEXT PRIMARY KEY, Value TEXT);
INSERT OR REPLACE INTO Variables VALUES ('VarStr', 'Val1');
INSERT OR REPLACE INTO Variables VALUES ('VarInt', 123);
INSERT OR REPLACE INTO Variables VALUES ('VarBlob', x'12345678');
SELECT Value
FROM Variables
WHERE Name = 'VarStr'
UNION ALL
SELECT Value
FROM Variables
WHERE Name = 'VarInt'
UNION ALL
SELECT Value
FROM Variables
WHERE Name = 'VarBlob';
Herman's solution worked for me, but the ... had me mixed up for a bit. I'm including the demo I worked up based on his answer. The additional features in my answer include foreign key support, auto incrementing keys, and use of the last_insert_rowid() function to get the last auto generated key in a transaction.
My need for this information came up when I hit a transaction that required three foreign keys but I could only get the last one with last_insert_rowid().
PRAGMA foreign_keys = ON; -- sqlite foreign key support is off by default
PRAGMA temp_store = 2; -- store temp table in memory, not on disk
CREATE TABLE Foo(
Thing1 INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
);
CREATE TABLE Bar(
Thing2 INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
FOREIGN KEY(Thing2) REFERENCES Foo(Thing1)
);
BEGIN TRANSACTION;
CREATE TEMP TABLE _Variables(Key TEXT, Value INTEGER);
INSERT INTO Foo(Thing1)
VALUES(2);
INSERT INTO _Variables(Key, Value)
VALUES('FooThing', last_insert_rowid());
INSERT INTO Bar(Thing2)
VALUES((SELECT Value FROM _Variables WHERE Key = 'FooThing'));
DROP TABLE _Variables;
END TRANSACTION;
To use the one from denverCR in your example:
WITH tblCTE AS (SELECT "Joe" AS namevar)
SELECT * FROM table, tblCTE
WHERE name = namevar
As a beginner I found other answers too difficult to understand, hope this works
Creating "VARIABLE" for use in SQLite SELECT (and some other) statements
CREATE TEMP TABLE IF NOT EXISTS variable AS SELECT '2002' AS _year; --creating the "variable" named "_year" with value "2002"
UPDATE variable SET _year = '2021'; --changing the variable named "_year" assigning "new" value "2021"
SELECT _year FROM variable; --viewing the variable
SELECT 'TEST', (SELECT _year FROM variable) AS _year; --using the variable
SELECT taxyr FROM owndat WHERE taxyr = (SELECT _year FROM variable); --another example of using the variable
SELECT DISTINCT taxyr FROM owndat WHERE taxyr IN ('2022',(SELECT _year FROM variable)); --another example of using the variable
DROP TABLE IF EXISTS variable; --releasing the "variable" if needed to be released
After reading all the answers I prefer something like this:
select *
from table, (select 'name' as name) const
where table.name = const.name
Try using Binding Values. You cannot use variables as you do in T-SQL but you can use "parameters". I hope the following link is usefull.Binding Values
I found one solution for assign variables to COLUMN or TABLE:
conn = sqlite3.connect('database.db')
cursor=conn.cursor()
z="Cash_payers" # bring results from Table 1 , Column: Customers and COLUMN
# which are pays cash
sorgu_y= Customers #Column name
query1="SELECT * FROM Table_1 WHERE " +sorgu_y+ " LIKE ? "
print (query1)
query=(query1)
cursor.execute(query,(z,))
Don't forget input one space between the WHERE and double quotes
and between the double quotes and LIKE