How to create correct SQL statement in delphi - sql

I am pretty new to delphi and I would like to ask how can I create a correct SQL statement / SQL string in delphi.
I have tried something like this:
sql:='use [TestovaciaDb] INSERT INTO [dbo].[client]([Meno],[Priezvisko]) VALUES('+name+','+surname+')';
I am using MS SQL server 2012
But I am getting a exception there. Thank you
EDIT:
meno and priez are variables with values from TEdit1 and TEdit2:
meno:= Edit1.Text;
priez:= Edit2.Text;

Use parameterized queries. You set the database in your ConnectionString, so you don't need to `use' it in your query.
ADOQuery1.SQL.Text := 'INSERT INTO [dbo].[client] ([Meno],[Priezvisko]) ' +
'VALUES(:Meno, :Priezvisko)';
ADOQuery1.Parameters.ParamByName('Meno').Value := Edit1.Text;
ADOQuery1.Parameters.ParamByName('Priezvisko').Value := Edit2.Text;
ADOQuery1.ExecSQL;

Remove the use [xxx] at the begining of the statement. The connection you use must be already configured to point to the correct database. Just like many others said, avoid creating your sentences by using constants, instead, use paramenters.

http://docwiki.embarcadero.com/Libraries/XE3/en/System.SysUtils.QuotedStr
Use QuotedStr function.
For example
sql:='use [TestovaciaDb] INSERT INTO [dbo].[client]([Meno],[Priezvisko]) VALUES('+QuotedStr(name)+','+QuotedStr(surname)+')';
Use QuotedStr to convert the string S to a quoted string. A single quotation mark (') is inserted at the beginning and end of S, and each single quotation mark in the string is repeated. To remove the quotation marks from a quoted string, use the AnsiDequotedStr routine.

Related

' on a procedure/function

I dont know when put '.
For example on a procedure, When i write execute immediate 'sentence'
if there are one value in the sentenece i put
'||valor||'
but on a function i dont know why i had to write
return 'UPPER(USER_NAME) = ''' || user || '''';
not only '||user||'.
Anyone can help me?
Don`t construct your query with concatenated values.
Use something like that instead
EXECUTE IMMEDIATE 'SELECT user_id FROM user_table WHERE UPPER( username ) = :1' INTO your_user_id USING UPPER( your_user_name );
It will handle all cases. In your example, what will happen if user contains a ' ? What if you have 2 successive ' ? It can be a real nightmare to handle.
Here's some examples from Oracle
user is a string in SQL and should be quoted in the SQL query: Your final query, apart from any escaping, should read UPPER(USER_NAME) = 'user', not UPPER(USER_NAME) = user.
But the whole query fragment is a string in PL/SQL, so you have to put a string in a string. To get the quotes for the SQL string in the PL/SQL string, you need to double them to 'escape' them, so Oracle doesn't think that the PL/SQL string itself ends.
So when you write '''', the outer quote define the boundaries of the (PL/SQL) string itself, and the inner two quotes are a single escaped quote inside that string.
Anyway, while this may be the actual answer to your question, and definitely helpful if you would need an empty set of quotes or a fixed string in your query, in general it's way better to use parameterized queries, so I urge you to follow Luc M's example.
here whatever comes within two single quotes(') will be considered as string. but what if you needed a string with single quotes within itself.
example,
if you need a word - sample - for a variable, it can be simply declared as l_var := 'sample'.
but if the string is needed with single quotes like - 'It's sample'??
in this case if we let as it is, the sql engine will read from first single quote to next single quote,.. likewise...
in this case we will use single quotes multiple times as required.
it can be referred from below example:
declare
single_quote_string varchar2(20):= 'sample';
multi_quote_string varchar2(20):= 'It''s sample';
multi_quote2_string varchar2(20):= '''It''s sample''';
begin
dbms_output.put_line('single_quote_string:'||single_quote_string);
dbms_output.put_line('multi_quote_string:'||multi_quote_string);
dbms_output.put_line('multi_quote2_string:'||multi_quote2_string);
end;
--output
single_quote_string:sample
multi_quote_string:It's sample
multi_quote2_string:'It's sample'
in your question , you were asking about use of : return 'UPPER(USER_NAME) = ''' || user || ''''; in execute immediate statement.
execute immediate is used to execute a string.
in your case, it's the where condition of user name.
when having normal sql, we will be having
upper(username) = 'SAMPLE';
but here this condition has to be passed as string to execute immediate command, meaning the single quotes which we use normally must be passed as a string, and hence we using multiple times.
if still not clear, you can try to display the execute immediate statement that you using in your code, which will output the sql command that you trying to run in execute immediate command.

How to escape special characters like " in the SQL query in order to avoid Injection

Using delphi 2010, i am wondering if there someway to escape the following string to make it safe from sql injection attacks :
my string :
SQLQuery1.SQL.Text := 'SELECT * FROM registered WHERE email="'+
email+'" and login_pass="'+password+'"';
How to rewrite this string, to make it safer than it is when someone type " in my TEditbox as his email or password !
Use parameters, and let the database drivers handle that stuff.
SQLQuery1.SQL.Text := 'SELECT * FROM registered WHERE email= :email'+
' and login_pass = :password';
SQLQuery1.ParamByName('email').AsString := EMail;
SQLQuery1.ParamByName('password').AsString := Password;
the basic replacement of ' with '' should make sure that you won't get injected in textual fields.
As a rule of thumb, make sure all inputs you add to the database are in the pattern you expect them to be.
in the case of email addresses, zip codes and passwords- you can define a simple regex to verify the validity.
keep in mind, that numeric fields can be also injected and should be verified as well.
If for whatever reason you can't use parameters, you can use a function like this:
USES SysUtils;
FUNCTION QuotedStr(CONST S : STRING) : STRING;
BEGIN
Result:='"'+ReplaceStr(S,'"','""')+'"'
END;
and then
SQLQuery1.SQL.Text := 'SELECT * FROM registered WHERE email='+
QuotedStr(email)+' and login_pass='+QuotedStr(password);
(this assumes that your database provider uses double quotes to delimit strings with and that two consecutive double quotes in a quoted string is really a single double quote, ie. one double quote).

Way to insert text having ' (apostrophe) into a SQL table

While I was trying the following SQL command , I got sql error.
INSERT INTO exampleTbl VALUES('he doesn't work for me')
where doesn't contain the apostrophe.
What is the way to insert text having ' (apostrophe) into a SQL table.
In SQL, the way to do this is to double the apostrophe:
'he doesn''t work for me'
However, if you are doing this programmatically, you should use an API that accepts parameters and escapes them for you automatically. Programmatically escaping and using string concatenation to assemble a query yourself is a sure way to end up with SQL injection vulnerabilities.
INSERT INTO exampleTbl VALUES('he doesn''t work for me')
If you're adding a record through ASP.NET, you can use the SqlParameter object to pass in values so you don't have to worry about the apostrophe's that users enter in.
$value = "he doesn't work for me";
$new_value = str_replace("'", "''", "$value"); // it looks like " ' " , " ' ' "
INSERT INTO exampleTbl (`column`) VALUES('$new_value')
try this
INSERT INTO exampleTbl VALUES('he doesn''t work for me')
insert into table1 values("sunil''s book",123,99382932938);
use double apostrophe inside of single apostrophe,
it will work
I know the question is aimed at the direct escaping of the apostrophe character but I assume that usually this is going to be triggered by some sort of program providing the input.
What I have done universally in the scripts and programs I have worked with is to substitute it with a ` character when processing the formatting of the text being input.
Now I know that in some cases, the backtick character may in fact be part of what you might be trying to save (such as on a forum like this) but if you're simply saving text input from users it's a possible solution.
Going into the SQL database
$newval=~s/\'/`/g;
Then, when coming back out for display, filtered again like this:
$showval=~s/`/\'/g;
This example was when PERL/CGI is being used but it can apply to PHP and other bases as well. I have found it works well because I think it helps prevent possible injection attempts, because all ' are removed prior to attempting an insertion of a record.
yes, sql server doesn't allow to insert single quote in table field due to the sql injection attack. so we must replace single appostrophe by double while saving.
(he doesn't work for me) must be => (he doesn''t work for me)
you can use backslash '\' if you want to display a single quote in your text.
INSERT INTO exampleTbl VALUES('He doesn(\')t') ;

Common Table Expression Error

I have to use old school ADODB (not ADO.NET) to execute a statement that contains a Common Table Expression.
I am using (have to use) the SQLOLEDB provider.
The DML statement works fine when executing from a Windows 7 / Windows Server 2008 client but not from WinXP or Win2K3 server.
I have profiled the routine and found that the old OSes send a slightly different SQL statement.
Win7 + 2008 = exec sp_executesql N'WITH source(Vsl, Cpt, SrcTyp, SrcNum, Opn, JobNum, Qty, Cst, Vry, Reg, Vnt, Sbk) AS ...'
WinXP + Win2K3 = exec sp_executesql N'exec WITH source(Vsl, Cpt, SrcTyp, SrcNum, Opn, JobNum, Qty, Cst, Vry, Reg, Vnt, Sbk) AS ...'
Notice the extra 'exec' slipped into the command text.
It appears as if the verions of SQLOLEDB.1 on the old OSs mis-treats the WITH statement and sees it as needing a prepending 'exec'.
Can anyone shed some light on this. Is there an SQLOLEDB driver update that I can apply to the old OSes? or some other workaround.
(FYI, You should really revisit some of your existing questions, as most of them seem to have helpful answers that appear to address the question; your comments even suggest this is so. If they have an answer, please accept it).
If you really need to use a CTE here (meaning you're doing something recursive and aren't just using it for convenience instead of inline-selecting or inline-joining), the simplest and fastest workaround would probably be to include your SQL within your own call to sp_executesql. You'll end up nesting calls to it (which will look silly), but it shouldn't cause any actual problems.
Wrapping the query up in an sp_executesql statement works great if you don't have parameters in the query, otherwise the parameters aren't parsed because they're in a quoted string by the time they get to ADO, and this results in a syntax error.
What I did to resolve this was to create a TADOQuery descendant, which overrides the constructor, as follows:
constructor TCPADOQuery.Create(AOwner: TComponent);
begin
inherited;
TWideStringList(SQL).OnChange := LocalQueryChanged;
end;
LocalQueryChanged then checks if the query starts with a common table expression, and inserts a dummy declaration at the beginning of the query, which the XP ADO parser does understand. A CTE must be preceded by a semicolon if it is not the first statement in the query, so we have to fix that first:
procedure TCPADOQuery.LocalQueryChanged(Sender: TObject);
var
a: WideString;
begin
if not (csLoading in ComponentState) then
Close;
a := Trim(SQL.Text);
if Uppercase(copy(a, 1, 4)) = 'WITH' then a := ';' + a;
if Uppercase(copy(a, 1, 5)) = ';WITH' then
a := 'DECLARE #DummyForADO_XP BIT'#13#10 + a;
CommandText := a;
end;
This has resolved the problem, and has saved me having to rework all of my code where I use both CTEs and parameters.

How can I escape single and double quotes in SQL prepared statement?

I have a SQL statement similar to the one shown below in Perl:
my $sql="abc..TableName '$a','$b' ";
The $a is free text which can contain anything including single quotes, double quotes, back- and front-slash characters, etc.
How can these characters be escaped to make the SQL statement work?
Thanks.
You can either use the ->quote method (assuming you're using DBI):
my $oldValue = $dbh->quote('oldValue');
my $newValue = $dbh->quote('newValue');
$dbh->do("UPDATE myTable SET myValue=$newValue where myValue=$oldValue");
Better still, the best practice is to use bind values:
my $sth = $dbh->prepare('UPDATE myTable SET myValue=? WHERE myValue=?');
$sth->execute('newValue','oldValue');
This should also work for stored procedure calls, assuming the statement once the strings have been expanded is valid SQL. This may be driver/DB specific so YMMV.
my $sth = $dbh->prepare("DBName..ProcName ?,? ");
$sth->execute($a, $b);
Use a prepared statement. Replace the variable with a ?. To crib an example from DBI manpages:
$sql = 'SELECT * FROM people WHERE lastname = ?';
$sth = $dbh->prepare($sql);
$sth->execute($user_input_here);
Interpolating user input into your SQL is asking for security holes.
If you use query parameter placeholders, you don't have to escape the content of the strings.
my $sql="DBName..ProcName ?, ?";
$sth = $dbh->prepare($sql);
$sth->execute($a, $b);
If the DBI is using true query parameters, it sends the parameter values to the RDBMS separately from the SQL statement. The values are never combined with the SQL statement string, therefore the values never have an opportunity to cause SQL injection.
If the DBI is "emulating" prepared statements by interpolating the variables into the query string, then DBI should handle the correct escaping logic so you don't have to. Let the experts (those who write and test DBI) worry about how to do it.
If you don't want to use ->quote (for some reason, this function doesn't run on my version of DBI) then try this:
$query=~s/\"/\\\"/g;
I tend to do the same with single quotes and commas too just to be safe.
Seems to work fine for me...!