I need to update multiple rows of a PLSQL table, something like this:
StringBuilder stringBuilder = new StringBuilder(
"UPDATE review_item SET LAST_MODIFIED_TIMESTAMP = systimestamp, ")
.append("target_urn = ?, ")
.append("assignee_urn = NULL WHERE item_id in (")
.append(StringUtils.join(itemIds, ","))
.append(")");
PreparedStatement ps = connection.prepareStatement(stringBuilder.toString());
OracleUtil.bindInput(ps, 1, getRandomUuid(), dbClauses.getQueuePostCleanState());
Issue is - I need all the rows to get updated with a different random guid, in this case it is getting updated with the same one. Any way to do this?
Related
Need to modify the data in an SQLite database that has fields similar to:
hash (string)
modTime (long, time in ms)
data (any data, e.g. string)
I know the hash value of the record to set the data for (it's really xxHash of some binary blob). There can be several records with the same hash, but I need to modify only the one with MAX(modTime) value with the matching hash... Can't figure out how to construct the UPDATE command.
You can use NOT EXISTS in the WHERE clause:
UPDATE tablename
SET data = new_data
WHERE hash = ?
AND NOT EXISTS (SELECT 1 FROM tablename t WHERE t.hash = tablename.hash AND t.modTime > tablename.modTime)
Or use the column rowid to find the row that you want to update:
UPDATE tablename
SET data = new_data
WHERE rowid = (SELECT rowid FROM tablename WHERE hash = ? ORDER BY modTime DESC LIMIT 1)
or with FIRST_VALUE() window function:
UPDATE tablename
SET data = new_data
WHERE rowid = (SELECT DISTINCT FIRST_VALUE(rowid) OVER (ORDER BY modTime DESC) FROM tablename WHERE hash = ?)
Replace new_data with the new value of data and ? with the value of hash you search for.
I want to insert a Dataframe in a table using ODBC.jl , the table already exists and it seems that i can't use the function ODBC.load with it (even with the append=true).
usually i insert DataFrames with copyIn by loading the dataframe as a csv but with just ODBC it seems i can't do that .
The last thing i found is :
stmt = ODBC.prepare(dsn, "INSERT INTO cool_table VALUES(?, ?, ?)")
for row = 1:size(df, 1)
ODBC.execute!(stmt, [df[row, x] for x = 1:size(df, 2)])
end
but this is line by line , it's incredibly long to insert everything .
I tried also to do it myself like this :
_prepare_field(x::Any) = x
_prepare_field(x::Missing) = ""
_prepare_field(x::AbstractString) = string(''', x, ''')
row_names = join(string.(Tables.columnnames(table)), ",")
row_strings = imap(Tables.eachrow(table)) do row
join((_prepare_field(x) for x in row), ",") * "\n"
end
query = "INSERT INTO $tableName($row_names) VALUES $row_strings"
#debug "Inserting $(nrow(df)) in $tableName)"
DBInterface.execute(db.conn, query)
but it throw me an error because of some "," not at the right place at like col 9232123
which i can't find because i have too many lines , i guess it's the _prepare_field that doesn't cover all possible strings escape but i can't find another way .
Did i miss something and there is a easier way to do it ?
Thank you
I am having a transaction that needs to run on sqlite. The Transaction includes several queries. If built separately (line by line) it works but it requires the call of dbSendQuery n-times. It slows down the code quite a bit.
The ideal code should look like this, but multiline query fails:
library("RSQLite")
con <- dbConnect(RSQLite::SQLite(), dbname="test.db")
dbSendQuery(con, paste("CREATE TABLE Variables (Name TEXT PRIMARY KEY, RealValue REAL, IntegerValue INTEGER, BlobValue BLOB, TextValue TEXT)"))
dbSendQuery(con, paste("INSERT INTO Variables (Name) VALUES ('newid');"))
dbSendQuery(con, paste("BEGIN IMMEDIATE TRANSACTION;",
"UPDATE Variables SET TextValue = '0' WHERE Name = 'newid';",
"UPDATE Variables SET RealValue = 0 WHERE Name = 'newid';",
"UPDATE Variables SET IntegerValue = 0 WHERE Name = 'newid';",
"COMMIT;",sep=" "))
a <- dbFetch(dbSendQuery(con, paste("SELECT * FROM _Variables;")))
dbSendQuery(con, paste("COMMIT;"))
Consider the RSQLite methods: dbBegin() and dbCommit() (w/ dbRollback for any errors) to handle transactions. Even consider combining all UPDATE statements into one:
library("RSQLite")
con <- dbConnect(RSQLite::SQLite(), dbname="test.db")
dbSendStatement(con, "CREATE TABLE [Variables] ([Name] TEXT PRIMARY KEY, [RealValue] REAL, [IntegerValue] INTEGER, [BlobValue] BLOB, [TextValue] TEXT)")
dbSendStatement(con, "INSERT INTO [Variables] ([Name]) VALUES ('newid')")
dbBegin(con)
tryCatch({
dbSendStatement(con, "UPDATE [Variables] SET TextValue = '0', RealValue = 0, IntegerValue = 0 WHERE [Name] = 'newid'")
}, error=function(e) dbRollback(con))
dbCommit(con)
a <- dbGetQuery(con, "SELECT * FROM [Variables]")
You can even combine UPDATE statement into one query:
I am not familiar with SQL that much. I'm trying to insert multiple rows of data into a table that if there exist a row with with duplicate value in BusinessFilterPhrase column then just don't insert. I wrote a pseudocode of what I think it should be.
if (filterCategoryList != null)
{
foreach (KeyValuePair<string, int> filter in filterCategoryList)
{
cmd.CommandText = "insert into tblBusinessName (BusinessFilterPhrase,BusinessCategoryID)" +
"select #BusinessFilterPhrase,#BusinessCategoryID" +
"from tblBusinessName as t1" +
"where NOT EXISTS" +
"( select * from tblBusinessName as d1 where d1.BusinessFilterPhrase = #BusinessFilterPhrase) ";
cmd.Parameters.AddWithValue("#BusinessFilterPhrase", filter.Key);
cmd.Parameters.AddWithValue("#BusinessCategoryID", filter.Value.ToString());
cmd.ExecuteNonQuery();
}
}
You code looks correct. I would write it as:
insert into tblBusinessName(BusinessFilterPhrase, BusinessCategoryID)
select #BusinessFilterPhrase, #BusinessCategoryID
from tblBusinessName t1
where NOT EXISTS (select 1
from tblBusinessName d1
where d1.BusinessFilterPhrase = #BusinessFilterPhrase
)
(The changes are only cosmetic.)
EDIT:
If performance is an issue, create an index on BusinessFilterPhrase:
create index idx_tblBusinessName_BusinessFilterPhrase on tblBusinessName(BusinessFilterPhrase);
You can make this a unique index, if you want the database to enforce the uniqueness of the column (it will generate an error when duplicate values would be inserted).
I want to add data to table STATISTICS using INSERT statements.
I also want to move new counts to old counts and new date to old date as the new data comes in.
This is where it gets lil tricky because I don't know if there is such a thing as INSERT INTO table with SET in Oracle.
INSERT INTO STATISTICS
SET
MODEL = '&MY_MODEL',
NEW_COUNT =
(
SELECT COUNT(*)
FROM TABLE CLIENTS
),
NEW_DATE = SYSDATE,
OLD_COUNT = NEW_COUNT,
OLD_DATE = NEW_DATE,
PRNCT_CHANGE = ((NEW_COUNT) - (OLD_COUNT)) / (NEW_COUNT)*100
);
How do I accomplish this in Oracle?
This should upsert statistics, adding new ones as you go. It presumes a unique key on MODEL; if that's not true, then you'd have to do inserts as Angelina said, getting only the most recent row for a single MODEL entry.
MERGE INTO STATISTICS tgt
using (SELECT '&MY_MODEL' AS MODEL,
(SELECT COUNT(*) FROM CLIENTS) AS NEW_COUNT,
SYSDATE AS DATE_COUNT,
NULL AS OLD_COUNT,
NULL OLD_DATE,
NULL AS PRCNT_CHANGE
FROM DUAL) src
on (TGT.MODEL = SRC.MODEL)
WHEN MATCHED THEN UPDATE
SET TGT.NEW_COUNT = SRC.NEW_COUNT,
TGT.NEW_DATE = SRC.NEW_DATE,
TGT.OLD_COUNT = TGT.NEW_COUNT,
TGT.OLD_DATE = TGT.NEW_DATE,
TGT.PRCNT_CHG = 100 * (SRC.NEW_COUNT - TGT.NEW_COUNT) / (SRC.NEW_COUNT)
-- NEEDS DIV0/NULL CHECKING
WHEN NOT MATCHED THEN INSERT
(MODEL, NEW_COUNT, NEWDATE, OLD_COUNT, OLD_DATE, PRCNT_CHANGE)
VALUES
(src.MODEL, src.NEW_COUNT, src.NEWDATE, src.OLD_COUNT, src.OLD_DATE, src.PRCNT_CHANGE);
INSERT INTO STATISTICS(MODEL,NEW_COUNT,NEW_DATE,OLD_COUNT,OLD_DATE,PRNCT_CHANGE)
SELECT MODEL,
( SELECT COUNT(*)
FROM TABLE(USERS)
),
SYSDATE,
NEW_COUNT,
NEW_DATE,
(((NEW_COUNT) - (OLD_COUNT)) / (NEW_COUNT)*100)
FROM SEMANTIC.COUNT_STATISTICS
WHERE MODEL = '&MY_MODEL'
AND trunc(NEW_DATE) = trunc(NEW_DATE -1)
;