how to run multiple SQL statements in a clientdataset or fdquery? - delphi-xe7

I'm using the statement below:
procedure TdtmdlImportacao.DeleteParticipante;
begin
fdqryDelete.Active := False;
fdqryDelete.SQL.Clear;
fdqryDelete.SQL.Add('DELETE FROM PARTICIPANTE');
fdqryDelete.ExecSQL;
end;
procedure TdtmdlImportacao.DeleteProduto;
begin
fdqryDelete.Active := False;
fdqryDelete.SQL.Clear;
fdqryDelete.SQL.Add('DELETE FROM PRODUTO');
fdqryDelete.ExecSQL;
end;
I would like to make a delete all.

Did you try:
begin
fdqryDelete.Active := False;
fdqryDelete.SQL.Clear;
fdqryDelete.SQL.Add('DELETE FROM PARTICIPANTE;');
fdqryDelete.SQL.Add('DELETE FROM PRODUTO;');
fdqryDelete.ExecSQL;
end;
with ";" at the end of each row inside ' '?

Related

Getting Error(42,1): PLS-00103: Encountered the symbol "END" on PlSQL code.

Using sql developer. I am a newbie to PLSQl. I have tried a lot of the solutions that have been suggested and a bunch that have not been suggested. Seems like I either get the "end" or "Begin" PLS-00103 error. Below is the code. Thanks in advance for any help - greatly appreciate it.
CREATE OR REPLACE PROCEDURE PROCEDURE1
(
category_id in Messages.category_id%type,
messagetext in Messages.messagetext%type,
lastupdatedBy in Messages.lastupdatedBy%type,
message_id out Messages.message_id%type,
txtcomment out varchar2)
as
BEGIN
Declare uniquecategoryid number := 0;
uniquemsgid number := 0;
BEGIN
-- verify that category id is a valid category
SELECT Categories.category_id
INTO uniquecategoryid
FROM Categories
WHERE Categories.category_id = PROCEDURE1.category_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
uniquecategoryid := 0;
END;
BEGIN
SELECT message_id into uniquemsgid
FROM Messages
where Messages.messagetext = PROCEDURE1.messagetext
AND uniquecategoryid > 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN
uniquecategoryid := 0;
END;
Begin
INSERT INTO Messages (CATEGORY_ID, messagetext, lastupdatedby, lastupdated, status)
VALUES (PROCEDURE1.category_id, PROCEDURE1.messagetext,
PROCEDURE1.lastupdatedBy, SYSDATE,'A')
returning Messages.message_id INTO PROCEDURE1.message_id;
COMMIT;
PROCEDURE1.txtcomment := 'SUCCESS';
end;
END;
END PROCEDURE1;
Remove the END; stated above END PROCEDURE1;. The code understands the end of procedure block by END PROCEDURE1;. END; is useless in this case.

Table locks in SQLite accessed by fireDAC

I'm working on porting a set of paradox tables to SQLite. In order to do so, I created a test application that simulates (somewhat) the current usage scenario: multiple users accessing the same DB file and performing simultaneous read and writes.
The application is very simple: it will start several threads that each create a connection, opens a table and will randomly read, update or insert inside the table.
Almost immediately, The application encounters a "database table locked" error. I have tried several things to attempt to work around it but nothing seems to work. What am I doing wrong ?
Here is the code internal to the threads:
procedure testDB(TargetFolder: string);
var
Conn: TFDConnection;
Table: TFDTable;
i: Integer;
begin
randomize;
Conn := TFDConnection.Create(nil);
try
Conn.DriverName := 'SQLite';
Conn.LoginPrompt := false;
Conn.Params.clear;
Conn.Params.Database := TPath.Combine(TargetFolder, 'testDB.sdb');
Conn.Params.Add('DriverID=SQLite');
// all this is the result of several attemp to fix the table locking error. none worked
Conn.Params.Add('LockingMode=Normal');
Conn.Params.Add('Synchronous=Normal');
Conn.UpdateOptions.UpdateMode := TUpdateMode.upWhereAll;
Conn.UpdateOptions.LockWait := True;
Conn.UpdateOptions.LockMode := TFDLockMode.lmPessimistic;
Conn.UpdateOptions.LockPoint := TFDLockPoint.lpImmediate;
Conn.UpdateOptions.AssignedValues := [uvLockMode,uvLockPoint,uvLockWait];
Conn.Open();
Conn.ExecSQL('CREATE TABLE IF NOT EXISTS ''test'' (''ID'' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,''data1'' TEXT NOT NULL,''data2'' INTEGER NOT NULL)');
Table := TFDTable.Create(nil);
try
table.Connection := Conn;
while True do
begin
case Trunc(Random(10)) of
0..3:
begin
table.Open('test');
try
if table.Locate('data1', 'name'+intToStr(Trunc(Random(10))),[TLocateOption.loCaseInsensitive]) then
begin
table.Edit;
table.FieldByName('data2').AsInteger := table.FieldByName('data2').AsInteger + 1;
table.Post;
end;
finally
table.close;
end;
end;
4..8:
begin
table.Open('test');
try
i := Trunc(Random(10));
if not table.Locate('data1', 'name'+ i.ToString,[TLocateOption.loCaseInsensitive]) then
begin
table.AppendRecord([null, 'name'+ i.ToString, 0]);
end;
finally
table.close;
end;
end
else
break;
end;
end;
finally
FreeAndNil(Table);
end;
finally
FreeAndNil(Conn);
end;
end;
Thanks to Victoria, I managed to find the right parameters.
Conn := TFDConnection.Create(nil);
try
Conn.DriverName := 'SQLite';
Conn.LoginPrompt := false;
Conn.Params.clear;
Conn.Params.Database := TPath.Combine(TargetFolder, 'testDB.sdb');
Conn.Params.Add('DriverID=SQLite');
Conn.Params.Add('SharedCache=False');
Conn.Params.Add('LockingMode=Normal');
Conn.Params.Add('Synchronous=Normal');
Conn.UpdateOptions.LockWait := True;
Conn.Open();
Thanks again

PLS-00103 ERROR, what is wrong in the code

CREATE OR REPLACE PROCEDURE proc2_del_rows
(v_tname VARCHAR2,
v_condition VARCHAR2 DEFAULT NULL)
AS
sql_stmt VARCHAR2(500);
where_clause VARCHAR2(200) := 'WHERE'||' '||v_condition;
BEGIN
IF v_condition IS NULL THEN
where_clause := NULL;
END IF;
sql_stmt := 'DELETE FROM :1'||' '||where_clause;
EXECUTE IMMEDIATE sql_stmt USING v_tname;
COMMIT;
END;
/
The table name can't be a bind variable. Do a DBMS_ASSERT on the input table name parameter and make sure it is a valid table name literal, and then directly concatenate it to the delete statement. This will at least protect you against sql injection.
I'd like to know the reason behind doing a delete using a procedure and granting execute on this procedure to individual users, rather than granting a delete on the table to a user directly, which would somewhat be easier to control/restrict. I don't see how this is better in terms on security if that is what you are going for.
CREATE or replace PROCEDURE proc2_del_rows
(v_tname VARCHAR2,
v_condition VARCHAR2 DEFAULT NULL)
AS
sql_stmt VARCHAR2(500);
where_clause VARCHAR2(200) := 'WHERE'||' '||v_condition;
BEGIN
IF v_condition IS NULL THEN
where_clause := NULL;
END IF;
sql_stmt := 'DELETE FROM '||v_tname||' '||where_clause;
EXECUTE IMMEDIATE sql_stmt;
END;
/
To include a single-quote character within a string literal you need to double up the single quotes, as in proc2_del_rows('EMP', 'JOB=''CLERK''').
Documentation here

Q-Quote in execute immediate PL/SQL

I have following Update statement:
UPDATE COL_VAL SET DESC_VALUE=q'['TOM','JOHN','MARIE','VANI','PUTIN']' WHERE TYPE_NAME||TYPE='OLDHOL' ;
When I put above q-qoute in execute immediate, PL/SQL is not able to recognize syntax.
DECLARE
upd_stmnt varchar2(4000);
BEGIN
upd_stmnt := q'[UPDATE COL_VAL SET DESC_VALUE=q'['TOM','JOHN','MARIE','VANI','PUTIN']' WHERE TYPE_NAME||TYPE='OLDHOL']';
EXECUTE IMMEDIATE upd_stmnt;
END;
/
Please help.
seems that you can't nest q quoted strings, please try this one
DECLARE
upd_stmnt varchar2(4000);
BEGIN
upd_stmnt := q'[UPDATE COL_VAL SET DESC_VALUE = '''TOM'',''JOHN'',''MARIE'',''VANI'',''PUTIN''' WHERE TYPE_NAME || TYPE='OLDHOL']';
EXECUTE IMMEDIATE upd_stmnt;
END;
/

i have a function in which i am using bulk bind and passing multiple i/p parameter using in operator its not getting binded

create or replace type branch_warehouse as object (wh_id number,wh_name varchar2(100))
create or replace type id_warehouse_list as table of branch_warehouse
function get_ware_house_branch(p_BRANCH_IDS varchar2) return id_warehouse_list is
l_warehouse_list id_warehouse_list := id_warehouse_list();
str varchar2(300);
begin
str := 'SELECT BRANCH_WAREHOUSE(w.wh_id, w.wh_name)
FROM POD_WAREHOUSE_MASTER W
where ( W.BRANCH_ID IN (:'|| p_BRANCH_IDS||'))';
execute immediate str bulk collect into l_warehouse_list using p_BRANCH_IDS;
return l_warehouse_list;
end;
if i use single i/p parameter using = : it gets binded, please guide
Re-write your function as follows:
function get_ware_house_branch(p_BRANCH_IDS varchar2)
return id_warehouse_list
is
l_warehouse_list id_warehouse_list := id_warehouse_list();
str varchar2(300);
begin
str := 'SELECT BRANCH_WAREHOUSE(w.wh_id, w.wh_name)
FROM POD_WAREHOUSE_MASTER W
where ( W.BRANCH_ID IN (' || p_BRANCH_IDS || '))';
execute immediate str bulk collect into l_warehouse_list;
return l_warehouse_list;
end;
This seems to work properly (see this SQLFiddle).
The only changes I made were those suggested in my earlier comment - the ":" was removed from the SQL string, and the using p_BRANCH_IDS was removed from the EXECUTE IMMEDIATE.
Share and enjoy.

Resources