I'm using FastReport4 in DelphiXE4.
I set Connection String at RunTime Like this:
ADOConnection.ConnectionString := ConStr;
ADOConnection.Connected := True;
AdoQuery1.Connection := ADOConnection;
So I cannot see preview in FastReport Designer!
I have a query like this:
AdoQuery.Sql.Text :='SELECT Table1.title,Table2.title FROM Table1 INNER JOIN Table2 ON (Table1.code=Table2.id);';
I have a problem with Field name in FastReport Designer.
I tested [frxDBDataset1."Table1.title"], but Field Not Found !
Then I changed Query Like This:
AdoQuery.Sql.Text :='SELECT Table1.title as f1,Table2.title as f2 FROM Table1 INNER JOIN Table2 ON (Table1.code=Table2.id);';
and in FastReport Designer:
[frxDBDataset1."f1"]
But same error occurred!
Solution:
Select frxDBDataset and clear all FieldAliasis then use this:
AdoQuery.Sql.Text :='SELECT Table1.title as f1,Table2.title as f2 FROM Table1 INNER JOIN Table2 ON (Table1.code=Table2.id);';
And:
[frxDBDataset1."f1"]
Related
I have a grid that connected to AdoDataset. i want read records from two table with join SQL, but save record in a table.
Read data:
adodataset.commandtext := 'select * from Table1 left join Table2 on Table1.ID = Table2.ID';
adodataset.Open;
I want save Table1 Fields only when post
You can use ReadOnly property of DBGrid.Columns. For example if you have a query like this:
ADODataSet1.CommandText := 'SELECT * FROM Table1 JOIN Table2 ON Table1.ID = Table2.ID';
Then your DBGrid will be like:
You can then make 3rd and 4th columns read only at design time or at run time by these codes:
DBGrid1.Columns[2].ReadOnly := True;
DBGrid1.Columns[3].ReadOnly := True;
Also note that if you want to delete records only from Table1 then you should run this code when ADODataSet1 is active:
ADODataSet1.Properties['Unique Table'].Value := 'Table1';
Update:
As suggested in comments it's a good idea to set desired fields ReadOnly at DataSet level:
ADODataSet1.FieldByName('ID_1').ReadOnly := True;
ADODataSet1.FieldByName('Table2_Value').ReadOnly := True;
First of all the query example in the commandtext is wrong / ambiguous. I don't know what you want to perform but I'm guessing you want to change/save data in a table. In this case, why don't you perform the update in sql? Let's say you have the primary key field called "id", and you want to save a field called "name" with another value.
var
id, NewName: string;
//...
begin
//...
id := adodataset.fieldbyname('id').AsString;
adodataset.connection.execute(
'UPDATE table1 SET name = ' + quotedstr(NewName) + ' WHERE id = ' + quotedstr(id)
);
// refresh the records by closing and reopening the adodataset
adodataset.close;
adodataset.open;
// move to the wanted record
adodataset.Locate('id', id, []);
Why not use TAdoQuery ?
Qry.Close;
Qry.SQL.Clear;
Qry.SQL.Add("select * from Table1 left join Table2 on Table1.ID = Table2.ID");
Qry.Open;
while not Qry.EOF do
begin
[do stuff]
Qry.Next;
end;
I need a stored procedure with dynamic select statement, in my case only adding desired column names in select. This is what I created, but I'm not sure If It's safe for SQL injections:
CREATE OR REPLACE PROCEDURE MySchema.Search(
columns IN VARCHAR2,
res_out OUT SYS_REFCURSOR)
IS
BEGIN
OPEN res_out FOR
'SELECT ' || columns ||' FROM MySchema.Table1';
END Search;
Is this fine or is It not safe ? When reading all examples I haven't noticed anything easy as this, but It works. If It's not safe for SQL injections, please show me how I should do It. Thanks for help in advance !
I will suggest to you use your PL/SQL like this: in the below PL/SQL it ensures that, if any of the SQL Injection statement is trying to invoke it will stop.
CREATE OR REPLACE PROCEDURE MySchema.Search(
columns IN VARCHAR2,
res_out OUT SYS_REFCURSOR)
IS
v_columns VARCHAR2(4000);
BEGIN
select listagg(column_name,',') within group(order by 1)
INTO v_columns
from all_tab_columns
where owner = 'MYSCHEMA'
and table_name = 'TABLE1'
and column_name in (select regexp_substr(columns,'[^,]+', 1, level)
from dual
connect by regexp_substr(columns, '[^,]+', 1, level) is not null
);
OPEN res_out FOR
'SELECT ' || v_columns ||' FROM MySchema.Table1';
END Search;
I am trying to copy over one row from my archive table to my original table.
Without my WHERE clause, the whole table of table2 gets copied to table1.
I don't want this of course. So based on the gridview's ID value listed, the table will copy over only the row whose ID is the same.
When I debug the lines I get the correct ID listed for DisplaySup.Rows(0).Cells(2).Text.
(
val_ID table2.V_ID%type
)
is
begin
execute immediate 'insert into table1 (select * from table2 where V_ID = val_ID)';
end;
Yet I get the error
ORA-00904: "VAL_ID": invalid identifier
Table2 and Table1 have identical columns; so they both have column titled V_ID. I am unsure why Val_ID is flagging an error.
VB.net line of coding:
SupArchive.Parameters.Add("val_ID", OleDbType.VarChar).Value = DisplaySup.Rows(0).Cells(2).Text
So I tried to reference: EXECUTE IMMEDIATE with USING clause giving errors
Like so to fix WHERE:
(
val_ID table2.V_ID%type
)
is
begin
execute immediate 'insert into table1 (select * from table2 where V_ID = '||val_ID||')';
end;
but I get error:
ORA-00904: "val_ID": invalid identifier
Any suggestions on how to fix my stored procedure?
UPDATE:
Tried to do the suggested:
(
val_ID table2.V_ID%type
)
AS
BEGIN
execute immediate 'insert into table1 (col1, col2, col3...)(select col1, col2, col3... from table2 where V_ID = :val_ID)' using val_ID;
end;
but get error:
ORA-00904: "col72": invalid identifier
for col72 after Select statement
EXAMPLE OF MY TABLES (both are identical) purpose of table2 is when a row is deleted in table1, table2 can re-create the user that was deleted
Table1
ID CompanyName FirstName LastName ....(72 cols)
Table2
ID CompanyName FirstName LastName... (72 cols)
You would do best to use a bind variable in your insert statement. Also, you need to list the columns you're inserting into as well as those you're inserting, to avoid the "too many values" error.
Eg:
declare
val_ID table2.V_ID%type := 1;
begin
execute immediate 'insert into table1 (col1, col2, ...) (select col1, col2, ... from table2 where V_ID = :val_ID)' using val_id;
end;
/
Although in this instance there is absolutely no need to use dynamic sql at all, so you could just do:
declare
val_id table2.v_id%type := 1;
begin
insert into table1 (col1, col2, ...)
select col1, col2, ...
from table2
where v_id = val_id;
end;
/
Don't forget to commit after you've run the procedure!
I have a long SQL text that I want to assign to a query SQL. I do this the following way:
SQL.Text:= 'SELECT T1.COLUMN1,T2.COLUMN2,T1COLUMN3..........,'+
' T1.COLUMNn FROM TABLE1 T1 INNER JOIN '+
' TABLE2 T2 ON T1.ID=T2.ID'+
' WHERE T1.COLUMN10=100'
The actual SQL is 20 times longer than this. My problem is with the line breaks. When I format the source code (Ctrl+D) it sometimes leaves the lines as I typed, but other times it deletes the line breaks and I get something like this:
'SELECT T1.COLUMN1,T2.COLUMN2,T1COLUMN3 ' + 'FROM TABLE1 T1 INNER JOIN '+ 'TABLE2 T2 ON T1.ID=T2.ID'
And this leads to a "line too long (more than 1023 charactes)" error. What's interesting is this does not happen with all lines. I can't catch the difference between the lines which will be affected and those that won't. I need a line break after or before the "+" sign. How do I do this?
You can also use the Add function.
SQL.Clear;
SQL.ADD('SELECT T1.COLUMN1,T2.COLUMN2,T1COLUMN3..........,');
SQL.ADD(' T1.COLUMNn FROM TABLE1 T1 INNER JOIN');
SQL.ADD(' TABLE2 T2 ON T1.ID=T2.ID');
SQL.ADD(' WHERE T1.COLUMN10=100');
Try to assign the value in every line:
SQL.Text := 'SELECT T1.COLUMN1,T2.COLUMN2,T1COLUMN3..........,';
SQL.Text := SQL.Text + ' T1.COLUMNn FROM TABLE1 T1 INNER JOIN ';
SQL.Text := SQL.Text + ' TABLE2 T2 ON T1.ID=T2.ID';
SQL.Text := SQL.Text + ' WHERE T1.COLUMN10=100';
I know it looks ugly, but I think it solves your problem.
I am preparing stored procedure with oracle .I m using multiple inner joins with the same table where an input parameter value is checked within each inner join. I want to eliminate particular inner join if the input parameter is null
You would need to use dynamic SQL to construct the appropriate query for the parameters like this:
PROCEDURE myproc (p1 VARCHAR2) IS
l_sql LONG;
l_cursor SYS_REFCURSOR;
BEGIN
l_sql := 'SELECT a, b, c FROM table1';
IF p1 IS NOT NULL THEN
l_sql := l_sql || ' JOIN table2 ON table2.x = table1.x';
END IF;
l_sql := l_sql || ' WHERE table1.y = :bind1';
OPEN l_cursor FOR l_sql USING 123;
...
END;