I am using Delphi Xe5 and ZeosLib to connect to a remote database on a web server.
I am using the following code to insert a record into a table. but everytime i insert and there is a (') in the name, i get an error.
The error says that my syntax is wrong,the (') in the variable messes with the sql statement.
How can i solve this problem.
Code:
Data.personel.Active:=false;
sqltext:=data.personel.SQL.Text;
data.personel.SQL.Text:='Insert Into personel (name,surname,id_number,gender,company_name,nature_of_business,position_at_company,type_of_post,renumeration,company_size,duties,benefits,document_id,date_created,date_record_added) ' +
'VALUES ('''+name1+''','''+surname+''','''+idnumber+''','''+gender+''','''+companyname+''','''+natureofbusiness+''','''+positionatcompany+''','''+typeofpost+''','''+renumeration+''','''+companysize+''','''+duties+''','''+benefits+''','''+DokID+''',+'''+FormatDateTime('yyyy-mm-dd',Date_Created)+''','''+FormatDateTime('yyyy-mm-dd',Date_added)+''')';
Data.personel.ExecSQL;
I know my method is not of the most neat, but i just need to solve the (') problem. Thank you for your assistance
For goodness sake, don't concatenate SQL. It leaves the door open for SQL injection, and it causes problems like the one you're experiencing now. Use parameterized SQL statements instead (see notes that follow):
data.personel.Active := False;
data.personel.SQL.Text := 'Insert Into personel'#13 +
'(name, surname, id_number, gender, company_name, nature_of_business,'#13 +
'position_at_company, type_of_post, renumeration, company_size,'#13 +
'duties, benefits, document_id, date_created, date_record_added)'#13 +
'values'#13 +
'(:name, :surname, :id_number, :gender, :company_name, :nature_of_business, '#13 +
':position_at_company, :type_of_post, :renumeration, :company_size,'#13 +
':duties, :benefits, :document_id, :date_created, :date_record_added)';
data.personel.ParamByName('name').AsString := name1;
data.personel.ParamByName('surname').AsString := surname;
data.personel.ParamByName('id_number').AsString := idnumber;
data.personel.ParamByName('gender').AsString := gender;
// repeat for remaining values
data.personel.ExecSQL;
Notes:
The #13 at the end of each portion of the SQL statement is a carriage return. It makes it so you don't have to worry about a space at the start or end of each line. The server will ignore them, as extra white space is meaningless in SQL statements. It's the same as hitting the enter key at the end of each line when you're testing your query in a database management tool.
I use the column name as the parameter name, preceeding it with the : that indicates it's a parameter. It makes it easy to tell which one goes with which - the :surname parameter goes with the surname column.
If you put the SQL statement into it's own query component, you can put all of the SQL in at designtime, instead of supplying it at runtime. This means that the server can cache the compiled statement in case you use it again in a short time, making your queries execute faster if you're using them in a loop. You just change the value assigned to the parameters in the loop, leaving the SQL.Text alone.
Because your app is only used internally and is not exposed to the web doesn't mean you should ignore the risks of SQL injection. All it takes is one disgruntled employee who decides to get even with you or your company and learns about the possibility - when they decide to type something you didn't intend into the right edit control and drop or change an important database or table, the damage is just as severe.
Related
I have my new Spring Boot project with SQL Server and I need to replace my MySQL native query on the Repository method in my old project with SQL Server native query. It's a complex query with the case when expression in where condition. When I try testing that query in SQL Server Management Studio it shows errors like the image below.
enter image description here
And here's my old native query use with MySQL on the Repository method I want to replace it with SQL Server
enter image description here
Please help me to find the solution.
Thank you in advance!!
This is what you have and what you should have posted as text within your question. As text it becomes searchable and copyable by people trying to help YOU.
case when #num = 1 then p.merchant_name = #query else 1=1 end
CASE is an expression in TSQL. It is not a control-of-flow construct like it is in many other languages. To use an "optional" filter, you need to construct a boolean expression using CASE which handles the "optional" attribute correctly. Often this is done with a bit more complexity using CASE like this:
case when #num = 1 and p.merchant_name <> #query then 0 else 1 end = 1
So here, CASE is used to return a value that can be tested in a comparison. There is no magic in using 0 or 1. Use any values of any type.
When #num is 1 and the values do NOT match, the THEN branch (0) is returned.
When #num is 1 and the values match, the ELSE branch (1) is returned.
When #num is anything but 1, the ELSE branch (1) is returned.
So when the CASE expression returns 0 (really - anything but 1), the row is ignored (removed from the resultset).
Given that your query is actually constructed in an application, you should considering dynamically building the query and adding parameters as needed. That will likely generate a more efficient query that can be better optimized by the database engine. Alternatively you can review this kitchen sink discussion and Erland's discussion of dynamic search conditions. TBH it looks like someone used #num as a kludge to avoid adding parameters for the eight specific filter values. If I want to filter on both merchant name and store name, I can't with this approach.
I'm trying to update a database in JavaFX using JDBC and Textfields ,
The first textfields, but I keep getting SQL syntax errors.
It's a simple update syntax , but I have to use the textfield.getText() in order to fill up the data.
I tried this as the query I'll execute:
UPDATE intervention
set "+update_textfield2.getText()+" = "+update_textfield3.getText()+"
WHERE ( Numdemande ="+update_textfield.getText()+"
To explain the code above : set the database field the user entered (update_textfield2) as the value the user entered (update_textfield3) where the "Numdemande" number is x (update_textfield)
While your code is unsafe, as explained in the comments, I'll answer on the assumption that your class has not yet covered SQL injection attacks.
As for your SQL statement itself, there are several problems.
First of all, you are using double quotes " instead of single quotes '. It is unclear which dialect of SQL you are using, but most, if not all, require single quotes when passing through Strings like this.
Secondly, you are wrapping your calls to the textField.getText()
methods in quotes, meaning you're telling SQL to use that text
literally.
You have not added a closing parentheses ()) at the end of your WHERE clause. The parentheses in this case, however, are not necessary.
In essence, you're trying to pass the following statement to SQL:
UPDATE intervention
set +update_textfield2.getText()+ = '+update_textfield3.getText()+'
WHERE ( Numdemande = '+update_textfield.getText()+'
Unless you have a field called +update_textfield2.getText()+ in your table, this statement will fail.
The following String would produce the correct statement:
String statement = "UPDATE intervention " +
"SET " + update_textfield2.getText() + " = " + update_textfield3.getText() +
"WHERE Numdemande = " + update_textfield.getText() + ";";
Side Note: Please learn the Java Naming Conventions and stick to them. In your code, you've used Snake Case when naming your TextField, but should be using Camel Case instead. An appropriate name for your TextField might be something like this instead: updateTextField1
I'm trying to insert some information to MySQL with Pascal, but when I run the program I get the error
unknown column 'mohsen' in field list
This is my code
procedure TForm1.Button1Click(Sender: TObject);
var
aSQLText: string;
aSQLCommand: string;
namee:string;
family:string;
begin
namee:='mohsen';
family:='dolatshah';
aSQLText:= 'INSERT INTO b_tbl(Name,Family) VALUES (%s,%s)';
aSQLCommand := Format(aSQLText, [namee, family]);
SQLConnector1.ExecuteDirect(aSQLCommand);
SQLTransaction1.Commit;
end;
How can I solve this problem?
It's because your
VALUES (%s,%s)
isn't surrounding the namee and family variable contents by quotes. Therefore, your back-end Sql engine thinks your mohsen is a column name, not a value.
Instead, use, e.g.
VALUES (''%s'',''%s'')
as in
Namee := 'mohsen';
Family := 'dolatshah';
aSQLText:= 'INSERT INTO b_tbl(Name,Family) VALUES (''%s'',''%s'')';
aSQLCommand := Format(aSQLText,[namee,family]);
In the original version of my answer, I explained how to fix your problem by "doubling up" single quotes in the Sql you were trying to build, because it seemed to me that you were having difficulty seeing (literally) what was wrong with what you were doing.
An alternative (and better) way to avoid your problem (and the one I always use in real life) is to use the QuotedStr() function. The same code would then become
aSQLText := 'INSERT INTO b_tbl (Name, Family) VALUES (%s, %s)';
aSQLCommand := Format(aSQLText, [QuotedStr(namee), QuotedStr(family)]);
According to the Online Help:
Use QuotedStr to convert the string S to a quoted string. A single quote character (') >is inserted at the beginning and end of S, and each single quote character in the string is >repeated.
What it means by "repeated" is what I've referred to as "doubling up". Why that's important, and the main reason I use QuotedStr is to avoid the Sql db-engine throwing an error when the value you want to send contains a single quote character as in O'Reilly.
Try adding a row containing that name to your table using MySql Workbench and you'll see what I mean.
So, not only does using QuotedStr make constructing SQL statements as strings in Delphi code less error-prone, but it also avoid problems at the back-end, too.
Just in case this will help anybody else I had the same error when I was parsing a python variable with a sql statement and it had an if statement in i.e.
sql="select bob,steve, if(steve>50,'y','n') from table;"
try as I might it coming up with this "unknown column y" - so I tried everything and then I was about to get rid of it and give it up as a bad job until I thought I would swap the " for ' and ' for "..... Hoooraaahh it works!
This is the statement that worked
sql='select bob,steve, if(steve>50,"y","n") from table;'
Hope it helps...
To avoid this sort of problem and SQL injection you should really look into using SQL parameters for this, not the Pascal format statement.
I just asked an SQL related question, and the first answer was: "This is a situation where dynamic SQL is the way to go."
As I had never heard of dynamic SQL before, I immediately searched this site and the web for what it was. Wikipedia has no article with this title. The first Google results all point to user forums where people ask more or less related questions.
However, I didn't find a clear definition of what a 'dynamic SQL' is. Is it something vendor specific? I work with MySQL and I didn't find a reference in the MySQL handbook (only questions, mostly unanswered, in the MySQL user forums).
On the other hand, I found many references to stored procedures. I have a slightly better grasp of what stored procedures are, although I have never used any. How are the two concepts related? Are they the same thing or does one uses the other?
Basically, what is needed is a simple introduction to dynamic SQL for someone who is new to the concept.
P.S.: If you feel like it, you may have a go at answering my previous question that prompted this one: SQL: How can we make a table1 JOIN table2 ON a table given in a field in table1?
Dynamic SQL is merely where the query has been built on the fly - with some vendors, you can build up the text of the dynamic query within one stored procedure, and then execute the generated SQL. In other cases, the term merely refers to a decision made by code on the client (this is at least vendor neutral)
Other answers have defined what dynamic SQL is, but I didn't see any other answers that attempted to describe why we sometimes need to use it. (My experience is SQL Server, but I think other products are generally similar in this respect.)
Dynamic SQL is useful when you are replacing parts of a query that can't be replaced using other methods.
For example, every time you call a query like:
SELECT OrderID, OrderDate, TotalPrice FROM Orders WHERE CustomerID = ??
you will be passing in a different value for CustomerID. This is the simplest case, and one that can by solved using a parameterized query, or a stored procedure that accepts a parameter, etc.
Generally speaking, dynamic SQL should be avoided in favor of parameterized queries, for performance and security reasons. (Although the performance difference probably varies quite a bit between vendors, and perhaps even between product versions, or even server configuration).
Other queries are possible to do using parameters, but might be simpler as dynamic SQL:
SELECT OrderID, OrderDate, TotalPrice FROM Orders
WHERE CustomerID IN (??,??,??)
If you always had 3 values, this is as easy as the first one. But what if this is a variable-length list? Its possible to do with parameters, but can be very difficult. How about:
SELECT OrderID, OrderDate, TotalPrice FROM Orders WHERE CustomerID = ??
ORDER BY ??
This can't be substituted directly, you can do it with a huge complicated CASE statement in the ORDER BY explicitly listing all possible fields, which may or may not be practical, depending on the number of fields available to sort by.
Finally, some queries simply CAN'T be done using any other method.
Let's say you have a bunch of Orders tables (not saying this is great design), but you might find yourself hoping you can do something like:
SELECT OrderID, OrderDate, TotalPrice FROM ?? WHERE CustomerID = ??
This can't be done using any other methods. In my environment, I frequently encounter queries like:
SELECT (programatically built list of fields)
FROM table1 INNER JOIN table2
(Optional INNER JOIN to table3)
WHERE (condition1)
AND (long list of other optional WHERE clauses)
Again, not saying that this is necessarily great design, but dynamic SQL is pretty much required for these types of queries.
Hope this helps.
Dynamic SQL is simply a SQL statement that is composed on the fly before being executed. For example, the following C# (using a parameterized query):
var command = new SqlCommand("select * from myTable where id = #someId");
command.Parameters.Add(new SqlParameter("#someId", idValue));
Could be re-written using dynamic sql as:
var command = new SqlCommand("select * from myTable where id = " + idValue);
Keep in mind, though, that Dynamic SQL is dangerous since it readily allows for SQL Injection attacks.
Dynamic SQL is a SQL built from strings at runtime. It is useful to dynamically set filters or other stuff.
An example:
declare #sql_clause varchar(1000)
declare #sql varchar(5000)
set #sql_clause = ' and '
set #sql = ' insert into #tmp
select
*
from Table
where propA = 1 '
if #param1 <> ''
begin
set #sql = #sql + #sql_clause + ' prop1 in (' + #param1 + ')'
end
if #param2 <> ''
begin
set #sql = #sql + #sql_clause + ' prop2 in (' + #param2 + ')'
end
exec(#sql)
It is exactly what Rowland mentioned. To elaborate on that a bit, take the following SQL:
Select * from table1 where id = 1
I am not sure which language you are using to connect to the database, but if I were to use C#, an example of a dynamic SQL query would be something like this:
string sqlCmd = "Select * from table1 where id = " + userid;
You want to avoid using dynamic SQL, because it becomes a bit cumbersome to keep integrity of the code if the query get too big. Also, very important, dynamic SQL is susceptible to SQL injection attacks.
A better way of writing the above statement would be to use parameters, if you are using SQL Server.
Rowland is correct, and as an addendum, unless you're properly using parameters (versus just concatonating parameter values inline from provided text, etc.) it can also be a security risk. It's also a bear to debug, etc.
Lastly, whenever you use dynamic SQL unwisely, things are unleashed and children are eaten.
To most databases, every SQL query is "dynamic" meaning that it is a program that is interpreted by the query optimiser given the input SQL string and possibly the parameter bindings ("bind variables").
Static SQL
However, most of the time, that SQL string is not constructed dynamically but statically, either in procedural languages like PL/SQL:
FOR rec IN (SELECT * FROM foo WHERE x = 1) LOOP
-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "static SQL"
..
END LOOP;
Or in client / host languages like Java, using JDBC:
try (ResultSet rs = stmt.executeQuery("SELECT * FROM foo WHERE x = 1")) {
// "static SQL" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
..
}
In both cases, the SQL string is "static" in the language that embeds it. Technically, it will still be "dynamic" to the SQL engine, which doesn't know how the SQL string is constructed, nor that it was a static SQL string.
Dynamic SQL
Sometimes, the SQL string needs to be constructed dynamically, given some input parameters. E.g. the above query might not need any predicate at all in some cases.
You might then choose to proceed to constructing the string dynamically, e.g. in PL/SQL:
DECLARE
TYPE foo_c IS REF CURSOR;
v_foo_c foo_c;
v_foo foo%ROWTYPE;
sql VARCHAR2(1000);
BEGIN
sql := 'SELECT * FROM foo';
IF something THEN
sql := sql || ' WHERE x = 1'; -- Beware of syntax errors and SQL injection!
END IF;
OPEN v_foo_c FOR sql;
LOOP
FETCH v_foo_c INTO v_foo;
EXIT WHEN v_foo_c%NOTFOUND;
END LOOP;
END;
Or in Java / JDBC:
String sql = "SELECT * FROM foo";
if (something)
sql += " WHERE x = 1"; // Beware of syntax errors and SQL injection!
try (ResultSet rs = stmt.executeQuery(sql)) {
..
}
Or in Java using a SQL builder like jOOQ
// No syntax error / SQL injection risk here
Condition condition = something ? FOO.X.eq(1) : DSL.trueCondition();
for (FooRecord foo : DSL.using(configuration)
.selectFrom(FOO)
.where(condition)) {
..
}
Many languages have query builder libraries like the above, which shine most when doing dynamic SQL.
(Disclaimer: I work for the company behind jOOQ)
Is it something vendor specific?
The SQL-92 Standard has a whole chapter on dynamic SQL (chapter 17) but it only applies to FULL SQL-92 and I know of no vendor that has implemented it.
I think what's meant is that you should build the query dynamically before executing it. For your other questions this means that you should select the table name you need first and the use your programming language to build a second query for doing what you want (what you want to do in the other question isn't possible directly like you want).
I'm trying to implement a facebook search in my system (auto suggest while typing).
I've managed to code all the ajax stuff, but I'm not sure how to query the database.
I've created a table called People which contains the fields: ID, FirstName, LastName, MiddleName, Email.
I've also created a FTS-index on all those fields.
I want to create a stored procedure that will get as a parameter the text inserted in the query box and returns the suggestions.
For example, When I will write in the textbox the query "Joh Do"
It will translate to the query:
select * from People where contains(*, '"Joh*"') and contains(*, '"Do*"')
Is there a way to do that in stored procedure?
P.S
I've tried to use the syntax
select * from People where contains(*,'"Joh*" and "Do*"')
but it didn't returned the expected results, probably because it needs to search the words on different fields. Is there a way to fix that?
Thanks.
Try
select *
from People
where (FirstName Like '%'+ #FirstName + '%') and
(MiddleName Like '%'+ #MiddleName + '%') and
(LastName Like '%'+ #LastName + '%')
Also you may want to restrict the results to only return a maximum of say 10 by using:
select top 10
EDIT 1:
OK I now understand the problem better. I would use dynamic sql thus:
First create a split function e.g. Example Split function using XML trick
Then use dynamic sql:
declare #tstr varchar (500)
set #tstr = ''
select #tstr =#tstr + ' Contains(*, ''"'+ val + '*")' + ' and '
from dbo.split(#SearchStr, ' ')
set #tstr = left(#tstr,len(#tstr)-4)
select #tstr
Declare #dsql as varchar(500)
set #dsql = 'select * from People where '+ #tstr
exec (#dsql)
Also please note as per Remus, be aware of SQL Injections, the use of sp_executesql (instead of EXEC) would be better.
The problem is the open list nature of the argument. I can be Joh, it can be Joh Do, it can be Joh Do Na and so on and so forth. You have two main alternatives:
parse the input in the web app (in ASP I assume) and then call an appropriate procedure for the number of entries (ie. exec usp_findSuggestions1 'Joh', exec usp_findSuggestions2 'Joh', 'Do', exec usp_findSuggestions1 'Joh', 'Do', 'Na'). The first procedure uses 1 contains, the second has 2 contains .. and contains ... and the last has 3. This may look totally ugly from a DRY, code design and specially code maintenance pov, but is actually the best solution as far as T-SQL is concerned, due primarily to the plan stability of these queries.
pass the input straight into a single stored procedure, where you can split it into components and build a dynamic T-SQL query with as many contains as necessary.
Both solutions are imperfect. Ultimately, you have two problems, and both have been investigated before to quite some depth:
the problem of passing a list to a T-SQL procedure. See Arrays and Lists in SQL Server 2005 and Beyond
the problem of an undetermined number of conditions in the WHERE clause, see The Curse and Blessings of Dynamic SQL
The AJAX Toolkit has the "AutoComplete" control that provides this functionality out of the box. It is very simple to use.
Look at a sample here