Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Muhammad.

Asked: March 12, 2018 - 6:15 am UTC

Last updated: March 14, 2018 - 6:25 am UTC

Version: 12.1

Viewed 1000+ times

You Asked

Greetings

I'm trying to include search criteria in below script's query ('select * from ' || p_tname ;) to fetch only those rows/employees which were hired during last 24 hours.

I have tried below --

SQL> create or replace procedure dump_table_to_csv( p_tname in varchar2, p_filename in varchar2)
authid current_user /* <<<== if you want... runs as "invoker" and runs with ROLES */
is
l_output utl_file.file_type;
l_theCursor integer default dbms_sql.open_cursor;
l_columnValue varchar2(4000);
2 3 4 5 6 7 l_status integer;
l_sysmodtime date;
l_query varchar2(1000)
default 'select * from ' || p_tname ||' where hiredate >= '||to_char(sysdate-1,'dd-mm-yyyy hh24:mi:ss');
l_colCnt number := 0;
l_separator varchar2(1);
l_descTbl dbms_sql.desc_tab;
begin
l_output := utl_file.fopen( 'XXD_UTL', p_filename, 'w' );
execute immediate
8 9 10 11 12 13 14 15 16 17 'alter session set nls_date_format=''dd-mon-yyyy hh24:mi:ss'' ';
dbms_sql.parse( l_theCursor, l_query, dbms_sql.native );
dbms_sql.describe_columns( l_theCursor, l_colCnt, l_descTbl );
for i in 1 .. l_colCnt loop
utl_file.put( l_output,
l_separator || '"' || l_descTbl(i).col_name || '"' );
dbms_sql.define_column( l_theCursor, i, l_columnValue, 4000 );
18 19 20 21 22 23 24 l_separator := ',';
end loop;
utl_file.new_line( l_output );
l_status := dbms_sql.execute(l_theCursor);
while ( dbms_sql.fetch_rows(l_theCursor) > 0 ) loop
l_separator := '';
for i in 1 .. l_colCnt loop
dbms_sql.column_value( l_theCursor, i, l_columnValue );
utl_file.put( l_output, l_separator || l_columnValue );
l_separator := ',';
end loop;
utl_file.new_line( l_output );
25 end loop;
dbms_sql.close_cursor(l_theC 26 ursor);
27 28 29 30 31 32 33 34 35 36 37 38 utl_file.fclose( l_output );
execute immediate 'alter session set nls_date_format=''dd-MON-yy'' ';
exception
when others then
execute immediate 'alter session set nls_date_format=''dd-MON-yy'' ';
39 40 41 42 43 raise;
44 end;
45 /

Procedure created.

SQL> exec dump_table_to_csv('scott.emp','scott.csv');
BEGIN dump_table_to_csv('scott.emp','scott.csv'); END;

*
ERROR at line 1:
ORA-00933: SQL command not properly ended
ORA-06512: at "SCOTT.DUMP_TABLE_TO_CSV", line 43
ORA-06512: at line 1


SQL>

Thanking you in anticipation

Regards,
Ahmad

and Connor said...

Some quick debugging shows the issue

SQL> set serverout on
SQL> declare
  2   p_tname varchar2(10) := 'EMP';
  3   l_query varchar2(1000) default 'select * from ' || p_tname ||' where hiredate >= '||to_char(sysdate-1,'dd-mm-yyyy hh24:mi:ss');
  4  begin
  5    dbms_output.put_line(l_query);
  6  end;
  7  /
select * from EMP where hiredate >= 12-03-2018 10:48:35

PL/SQL procedure successfully completed.

SQL> select * from EMP where hiredate >= 12-03-2018 10:48:35;
SP2-0552: Bind variable "48" not declared.


You are not building a valid query.

SQL> set serverout on
SQL> declare
  2   p_tname varchar2(10) := 'EMP';
  3   l_query varchar2(1000)
  4     default 'select * from ' || p_tname ||' where hiredate >= to_date('''||to_char(sysdate-1,'dd-mm-yyyy hh24:mi:ss')||''',''dd-mm-yyyy hh24:mi:ss'')';
  5  begin
  6    dbms_output.put_line(l_query);
  7  end;
  8  /
select * from EMP where hiredate >= to_date('12-03-2018 10:50:01','dd-mm-yyyy hh24:mi:ss')



But I stress... search this site for "SQL Injection". Be very very careful when letting people pass in portions of a SQL query.

Rating

  (2 ratings)

Comments are currently disabled for this question.

Comments

Elaborate

Moris, March 13, 2018 - 8:52 am UTC


But I stress... search this site for "SQL Injection". Be very very careful when letting people pass in portions of a SQL query. 

Please rewrite your simple example in order to avoid injection. Please do not put a link. Just rewrite this 3 lines example above in your answer.
Connor McDonald
March 13, 2018 - 11:46 am UTC

Please do not put a link. Just rewrite this 3 lines example above in your answer.


Sorry - I don't subscribe to the cut/paste method of solutions. I prefer people read and understand. Especially when it comes to the topic of data security. So I'll direct you to this excellent resource.

http://www.oracle.com/technetwork/database/features/plsql/overview/how-to-write-injection-proof-plsql-1-129572.pdf

Example

Moris, March 13, 2018 - 2:19 pm UTC

Sorry - I don't subscribe to the cut/paste method of solutions

Thats why I kindly ask to write the need in order to avoid injection.

Your code above is the following


SQL> set serverout on SQL> declare 2 p_tname varchar2(10) := 'EMP'; 3 l_query varchar2(1000) 4 default 'select * from ' || p_tname ||' where hiredate >= to_date('''||to_char(sysdate-1,'dd-mm-yyyy hh24:mi:ss')||''',''dd-mm-yyyy hh24:mi:ss'')'; 5 begin 6 dbms_output.put_line(l_query); 7 end; 8 / select * from EMP where hiredate >= to_date('12-03-2018 10:50:01','dd-mm-yyyy hh24:mi:ss')


How rewrite it to avoid SQL injection?


More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library