How to bulk insert in MariaDB? - spring

I want to ask about bulk insert of MariaDB
While I'm searching for get information about bulk insert,
I found a solution
That is
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
But I'm using list parameter in mybatis. so I can't use this solution
INSERT INTO RaffleData
(
raffleNo, storeNo, storeId, favoriteArea, modelId,
size, personName, personId, createDate_join1, createDate_join2,
createDate_web_join, email, birthDate, isOut, address,
creator, createDate, isDelete,
randomNo, rank2, fileNo
)
That is
<foreach item="item" separator="," collection="raffleDataList">
<![CDATA[
(
#{item.raffleNo}, #{item.storeNo}, #{item.storeId}, #{item.favoriteArea}, #{item.modelId},
#{item.size}, #{item.personName}, #{item.personId}, #{item.createDate_join1}, #{item.createDate_join2},
#{item.createDate_web_join}, #{item.email}, #{item.birthDate}, #{item.isOut}, #{item.address},
#{item.creator}, NOW(), false,
#{item.randomNo}, #{item.rank2}, #{item.fileNo}
)
]]>
I want to apply for extended bulk insert for optimize SQL query
But I don't know how to apply list parameters.
I'm not used to writing English Writing.
If you know about this problem, please solution to me

Related

How to determine if an Index is required for my Oracle query

i would like to know if an index is required or would help to run the below query? i dont have any idea how can i analyze this question.
if some one can help please thanks
WITH C(A0_ID, A1_ID, A1_Col0)
AS (
SELECT
Table_1.ID AS A0_ID,
Table_2.ID AS A1_ID,
Table_2.Col0 AS A1_Col0
FROM Table_1 ,Table_2
WHERE Table_2.ID = Table_1.ID
AND Table_1.col1 = ?
AND BITAND(Table_1.col2, ?) <> ?
AND Table_2.col3 IN (?,?,?)
), T(A0_ID, A1_ID, A1_Col0) AS (
SELECT
A0_ID,
A1_ID,
A1_Col0
FROM C
WHERE A1_ID = ?
UNION ALL
SELECT
C.A0_ID,
C.A1_ID,
C.A1_Col0
from C
INNER JOIN T P ON C.A1_Col0 = P.A1_ID
) SELECT A0_ID, A1_ID, A1_Col0 FROM T
The main query selects from T with no post-processing (filtering, aggregation, sorting, etc.), so it doesn't require optimization.
T is a recursive CTE based on the subquery C. Therefore, T doesn't need optimization (unless you materialized it, but that's a different story).
Now, C can be optimized:
I would consider Table_1 as the driving table since it has an equality in the filtering criteria. It also, uses ID to join against Table_2. Therefore a good index for it is:
create index ix1 on Table_1 (col1, ID);
Then, to access Table_2 you'll need to get through ID that should be the main index column. You may add col3 to the index to somewhat improve the performance of the query; only a benchmark will tell if this is a wise idea. The index could look like:
create index ix2 on Table_2 (ID, col3); -- col3 is optional here
I would recommend you create these indexes and compare the performance that each option produces.

(iBatis) I want to insert multiple data list in a table

I develop web application using Spring and iBatis. I want to insert multiple data in a table. I throw DataMap including ArrayList in controller as follow.
param.put("aList", aList);
param.put("aaaSeq", aaaSeq);
commonDAO.insert(namespace, "insertAAA", param);
In ibatis,
<insert id="insertAAA" parameterClass="dmap">
<selectKey keyProperty="aaaSeq" resultClass="java.lang.Integer" type="pre">
SELECT a_seq.nextval FROM DUAL
</selectKey>
insert into AAA
(
aSeq,
a,
)
<iterate property="aList" open="(" close=")" conjunction=" union all ">
select
#aaaSeq#,
#aList[]#
from
dual
</iterate>
</insert>
However, it have an error related with Integrity Constraints.
So, I wondering how to insert multiple data in a single table.

How can I perform a SELECT DISTINCT on all fields except a BLOB?

I'm trying to perform a SELECT DISTINCT query in Oracle, like this:
SELECT
MOVIES.TITLE, CERTIFICATIONS.ID, PROJECTION.DAY, TIME_SLOTS.SLOT,
PROJECTION.REMAINING_SEATS, IMAGES.IMAGE
FROM
[...]
It doesn't work because the column "IMAGES.IMAGE" is a BLOB. I would like to exclude this field from the DISTINCT (because I don't need it to be unique), and I don't know how. I also tried with a GROUP BY clause, but if I try to GROUP on all the fields except the BLOB, Oracle returns this error:
ORA-00979: not a GROUP BY expression
And if I add the field in the GROUP BY clause, then Oracle returns this:
ORA-00932: inconsistent datatypes: expected - got BLOB
What can I do?
SELECT DISTINCT MOVIES.TITLE, CERTIFICATIONS.ID, PROJECTION.DAY, TIME_SLOTS.SLOT, PROJECTION.REMAINING_SEATS
FROM [...]
Distinct is applied to all columns from the SELECT list. And yes, you cannot use LOBs in GROUP BY, UNION, DISTINCT etc because Oracle doesn't know how to compare different LOBs
If you want to retrieve BLOB as well you may try something like this:
SELECT MOVIES.TITLE, CERTIFICATIONS.ID,
PROJECTION.DAY, TIME_SLOTS.SLOT, PROJECTION.REMAINING_SEATS, IMAGES.IMAGE
FROM (
SELECT MOVIES.TITLE, CERTIFICATIONS.ID,
PROJECTION.DAY, TIME_SLOTS.SLOT, PROJECTION.REMAINING_SEATS, IMAGES.IMAGE,
row_number() over (partition by MOVIES.TITLE, CERTIFICATIONS.ID, PROJECTION.DAY, TIME_SLOTS.SLOT, PROJECTION.REMAINING_SEATS
order by PROJECTION.DAY, TIME_SLOTS.SLOT) RW
FROM [...]
) WHERE RW = 1;
But you should understand what are you looking for. For example, the query above group all the columns except a BLOB column, order them by some two columns and assign a row number to each row in the group. The resulting query retrieves only the first row in each group

Need to select column from subquery into main query

I have a query like below - table names etc. changed for keeping the actual data private
SELECT inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
I am selecting records from Invoice based on Order. i.e. all records from Invoice which are common with order records for today, based on those 3 columns...
Now I want to select Order_Num from Order in my select query as well.. so that I can use the whole thing to insert it into totally seperate table, let's say orderedInvoices.
insert into orderedInvoices(seq_no,..same columns as Inv...,Cr_dt)
(
SELECT **Order.Order_Num**, inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
)
?? - how to do I select that Order_Num in main query for each records of that sub query?
p.s. I understand that trunc(cr_dt) will not use index on cr_dt (if a index is there..) but I couldn't select records unless I omit the time part of it..:(
If the table ORDER1 is unique on CARRIER, PRO and N_DT you can use a JOIN instead of IN to restrict your records, it'll also enable you to select whatever data you want from either table:
select order.order_num, inv.*, trunc(sysdate)
from Invoice inv
join order ord
on inv.carrier = ord.carrier
and inv.pro = ord.pro
and inv.ndate = ord.n_dt
where trunc(order.cr_dt) = trunc(sysdate)
If it's not unique then you have to use DISTINCT to deduplicate your record set.
Though using TRUNC() on CR_DT will not use an index on that column you can use a functional index on this if you do need an index.
create index i_order_trunc_cr_dt on order (trunc(cr_dt));
1. This is a really bad name for a table as it's a keyword, consider using ORDERS instead.

Temporary tables in Packages - Oracle

I am kind of new in Oracle.
I am trying to create a package that has several functions.
This is the pseudocode of what I want to do
function FunctionA(UserID, startdate, enddate)
/* Select TransactionDate, Amount
from TableA
where TransactionDate between startdate and enddate
and TableA.UserID = UserID */
Return TransactionDate, Amount
end FunctionA
function FunctionB(UserID, startdate, enddate)
/* Select TransactionDate, Amount
from TableB
where TransactionDate between startdate and enddate
and TableB.UserID = UserID */
Return TransactionDate, Amount
end FunctionA
TYPE TRANSACTION_REC IS RECORD(
TransactionDate DATE,
TransactionAmt NUMBER);
function MainFunction(startdate, enddate)
return TBL
is
vTrans TRANSACTION_REC;
begin
FOR rec IN
( Select UserID, UserName, UserStatus
from UserTable
where EntryDate between startdate and enddate )
LOOP
vTrans := FunctionA(rec.UserID, startdate, enddate)
if vTrans.TransactionDate is null then
vTrans := FunctionB(rec.UserID, startdate, enddate)
if vTrans.TransactionDate is null then
rec.UserStatus := 'Inactive'
endif;
endif;
END Loop;
PIPE ROW(USER_OBJ_TYPE(rec.UserID,
rec.UserName,
rec.UserStatus,
vTrans.TransactionDate,
vTtans.TransactionAmt));
end MainFunction
Running this kind of code takes a long time because TableA and TableB is a very large table, and I am only getting 1 entry per record from the tables.
I would want to create a temporary table (TempTableA, TempTableB) within the package that will temporarily store all records based on the startdate and enddate, so that when I try to retrieve the TransactionDate and Amount for each rec, I will only refer to the TempTables (which is smaller than TableA and TableB).
I also want to take into consideration if the UserID is not found in TableA and TableB. So basically, when there are no records found in TableA and TableB, I also want the entry in the output, but it is indicated that the user is inactive.
Thank you for all your help.
SQL is a set-based language. It is far more efficient to execute one statement which returns all the rows you need than to execute many statements which each return a single row.
Here is one way of getting all your rows at once. It uses a common table expression because you read the whole of the UserTable and you should only do that once.
with cte as
(select UserID
, UserStatus
from UserTable )
select cte.UserID
, cte.UserStatus
, TableA.TransactionDate
, TableA.Amount
from cte join TableA
on (cte.UserID = TableA.UserID)
where cte.UserStatus = 'A'
and TableA.TransactionDate between startdate and enddate
union
select cte.UserID
, cte.UserStatus
, TableB.TransactionDate
, TableB.Amount
from cte join TableB
on (cte.UserID = TableB.UserID)
where cte.UserStatus != 'A'
and TableB.TransactionDate between startdate and enddate
By the way, be careful with temporary tables. They aren't like temporary tables in T-SQL. They are permanent heap tables, it's just their data that's temporary. This means that populating a temporary table is an expensive process, because the database writes all those rows to disk. Consequently we need to be certain that the performance gain we get by reading a dataset from a temporary table is worth the overhead of all those writes.
That certainly would not be the case with your code. In fact, it is really pretty rare that the answer to a performance question turns out to be "Use a Global Temporary Table", at least not in Oracle. Better queries are the way to go, and in particular, embracing the Joy of Sets!
Probably better to do it in one query, e.g.:
Select UserTable.UserID, UserTable.UserName, UserTable.UserStatus
,TableA.TransactionDate AS ATransactionDate
,TableA.Amount AS AAmount
,TableB.TransactionDate AS BTransactionDate
,TableB.Amount AS BAmount
from UserTable
left join TableA
on (UserTable.UserID = TableA.UserID)
left join TableB
on (UserTable.UserID = TableB.UserID)
where UserTable.EntryDate between startdate and enddate

Resources