I hand coded a simple SQL in SQL Server 2008 as below;
SELECT * FROM Tab1 WHERE
A='1' AND (B='1' OR C='1');
Being lazy I opened this query in the Query Editor to validate the syntax and pressed OK on the dialog without making any changes.
I noticed that the Query Editor had changed my query to:
SELECT * FROM Tab1 WHERE A='1' AND (B='1') OR (C='1');
clearly this changes the logic of the SQL and returns different results depending on which one you execute.
I routinely use the Query Editor to validate my syntax on complex queries. So a little worried that the a subtle change like this would go unotice, but would change the outcome.
Is this a feature of the designer? Is there something I can do to change this behavior?
EDIT: Thanks for pointing out that the changes made by the editor is not quite the same as above, but still the query is modified although the results are the same.
Thanks
I tried to replicate this in the Query Designer and had a slightly different result. I typed the same as you:
SELECT * FROM Tab1 WHERE A='1' AND (B='1' OR C='1');
And got this:
SELECT *
FROM Tab1
WHERE (A = '1') AND (B = '1') OR
(A = '1') AND (C = '1')
I have to say that the result is the same, but we can all see a dangerous road here. Also, I did not like the (A = '1') replication. Heck, I want the code how I coded it!
A word to the wise: I never format my queries in SQL Server Management Studio. Have you seen what it does to your view's code? I hate it. I just code somewhere else and paste in SMS when done.
The statement
SELECT * FROM Tab1 WHERE A='1' AND (B='1' OR C='1')
resolves for me to:
SELECT * FROM Tab1 WHERE (A='1') AND (B='1') OR (A='1') AND (C='1')
This is surprisingly correct, as in SQL Server TSQL the AND operator has precedence over OR. That means the above is the same like the following, because the AND-operator gets evaluated before the OR-operator:
SELECT * FROM Tab1 WHERE ((A='1') AND (B='1')) OR ((A='1') AND (C='1'))
And this is the same like the initial statement being used in the question.
See Operator Precedence (Transact-SQL) for details.
Related
I have a task to check and prove if there is a way to prevent SQL Injection without access to the database first - So no parameterized statements.
This basically means:
Is there a way to parse SQL statement as a string using any kind of tool or framework that would prove that SQL has been injected into it.
Any techniques available.
At first I had an idea to check if SQL matches a certain pattern like this:
Let somewhere be any kind of string that user can type in.
This is my SQL:
SELECT Id FROM somewhere
This statement has a pattern that looks like this:
SELECT SOME_VALUE FROM SOME_TABLE
Then let's say user wrote someTable WHERE 1=1; into the somewhere variable - (I know its not the smartest of SQL Injections)
But the point is now I have a statement that looks like this:
SELECT Id FROM someTable WHERE 1=1;
Which effectively gives us a statement that has a pattern like this:
SELECT SOME_VALUE FROM SOME_TABLE WHERE SOME_CONDITION
Which does not match the initial pattern:
SELECT SOME_VALUE FROM SOME_TABLE
Is that a correct way to check if SQL has been injected? I haven't found any tools that actually use this technique, or any other technique than just parameters (which require connection to the database). Don't worry - I know that parameters are the way to go, this task is about having no connection to the database.
It would be an idea if you block certain keywords and symbols like 'WHERE', 'AND', 'OR', ';', and '='.
But this is just a naive approach and for production, you should use parameterized statements.
The following query will not show up in design view and if you trying to make it show it locks up MS Access and you have to use the Task Manager to stop MS Access. The query actually runs and produces the correct results. If there is a better way I will certainly accept that.
SELECT
log_metric_N.metric_title,
log_metric_N.metric_N
FROM
(
SELECT
tref_log_metrics_weights_and_factors.metric_title,
[metric_base].[metric_count],
[metric_base].[metric_sum],
(([metric_base].[metric_count]*[tref_log_metrics_weights_and_factors].[metric_weight])/[metric_base].[metric_sum]) AS metric_N
FROM
tref_log_metrics_weights_and_factors,
(
SELECT
Count(tref_log_metrics_weights_and_factors.metric_weight) AS metric_count,
Sum(tref_log_metrics_weights_and_factors.metric_weight) AS metric_sum
FROM
tref_log_metrics_weights_and_factors
WHERE (((tref_log_metrics_weights_and_factors.metric_weight)<>0))
) as metric_base
) AS log_metric_N;
#HansUp you were exactly right on. I forgot all about the Domain functions and they work perfectly without the complexity. Below is the resultant SQL statement.
SELECT
tref_log_metrics_weights_and_factors.metric_title,
DCount("[metric_weight]","tref_log_metrics_weights_and_factors","[metric_weight]<>0") AS metric_count,
Dsum("[metric_weight]","tref_log_metrics_weights_and_factors") AS metric_sum,
(([metric_count]*[tref_log_metrics_weights_and_factors].[metric_weight])/[metric_sum]) AS metric_N
FROM
tref_log_metrics_weights_and_factors
I have to perform lexical analysis on the oracle query and separate the query to various parts (based on the clauses)in perl. For example,Consider :
Select deleteddate,deletedby from temptable where id = 10;
I need to print
select : deleteddate , deletedby
from : temptable
where : id = 10
I used this code snippet :
my $parser= SQL::Statement->new();
$parser->{PrinteError}=1;
my $query = SQL::Statement->new("select deleteddate,deletedby from temptable where id =10",$parser);
my #columns = $query->columns();
print $columns[0]->name();
Though this prints deleteddate, this fails when i give a subquery inside the select clause:
Select deleteddate,deletedby,(select 1+1 from dual) from temptable where id = 10;
Can you please point me in the correct direction.
Thanks.
It looks to be a limitation of that package; it seems to be a general purpose parser and not something that can understand advanced features like subqueries or Oracle-specific constructs like "from dual".
What are the constraints of your system? If python is an option it looks like this is a more fully-featured library:
http://code.google.com/p/python-sqlparse/
The other option would be to use the actual Oracle database, if that's an option. You would:
use the DBI and DBD::Oracle modules to create a connection to Oracle & get a database handle,
create a statement handle by calling prepare() on the database handle using your query,
execute the query (there may be an option in Oracle to execute in "test only" or "parse only" mode),
examine the statement handle (such as the NAMES_hash property) to get the column names.
Otherwise it seems the SQL::Statement module unfortunately just isn't up to the task...
I am getting some strange behavior involving database queries that I have never seen before and I'm hoping you can illuminate the issue.
I have a table of data called myTable with some columns; thus far everything involving it has been fine. Now, I've just added a column called subTitle; and II notice that the SELECT * Query that pulls in the data for a given record is not aware of that column (it says the returned query does not have a subTitle column), but if I explicitly name the column (select subTitle) it is. I thought perhaps that the Coldfusion server might be caching the query so I tried to work around with cachedwithin="#CreateTimeSpan(0, 0, 0, 0)#" but no dice.
Consider the below code:
<cfquery name="getSub" datasource="#Application.datasourceName#">
SELECT subTitle
FROM myTable
WHERE RecordID = '674'
</cfquery>
<cfoutput>#getSub.subTitle#</cfoutput>
<cfquery name="getInfo" datasource="#Application.datasourceName#">
SELECT *
FROM myTable
WHERE RecordID = '674'
</cfquery>
<cfoutput>#getInfo.subTitle#</cfoutput>
Keeping in mind that record 674 has the string "test" in it's subTitle column the about of the above is
test
[[CRASH WITH ERROR]]
This doesn't make sense to me unless SQL Server 2008 has somehow cached the SELECT * query with the previous incarnation of the table, but the strange thing is if I run the query right from within SQL Management Studio there are no problems and it shows all columns with the select *
Frankly this one has me baffled; I know I can get around this by explicitly naming all the desired columns in the select query instead of using * (which is best practice anyway), but I want to understand why this is occurring.
I've worked with SQL Server 2005 for many years and never had something like this happen, which leads me to believe it might involve something new in SQL Server 2008; but then again the fact that the query works fine inside of the management studio doesn't jive with that either.
===UPDATE===
Clearing the Template Cache in the CF admin will solve the issue
Yes, ColdFusion caches the <cfquery> SQL string. If the underlying table structure changes, the result might be an exception like you see it.
Work-arounds:
Recommended solutiuons:
If you have the development or enterprise version you can view your query cache in the server moniter and clear only the queries there. (comment from #Dpolehonski, thanks)
Otherwise, click Clear Template Cache Now in the ColdFusion Administrator (under Server Settings/Caching).
This will invalidate all cached CFML-Templates on the server and CF will re-compile them when necessary.
Quick and dirty:
Subtly change the query SQL, for example add a space somewhere. When you are on a development machine it's the quickest way to fix the issue.
This will invalidate the compiled version of this query only and force a re-compile.
(Note that removing the subtle change will trigger the error again since the old query text will remain cached.)
Brute-force:
Re-start the ColdFusion server. Brutal, but effective.
Or the quick and super dirty method:
<cfquery name="getInfo" datasource="#Application.datasourceName#">
SELECT
*, #createUUID()# as starQueryCacheFix
FROM
myTable
WHERE
RecordID = '674'
</cfquery>
Don't leave in production code though... it'll obsolete all of the query caching ColdFusion does. I did say it was super dirty ;)
I need to search through all of the stored procedures in an Oracle database using TOAD. I am looking for anywhere that the developers used MAX + 1 instead of the NEXTVAL on the sequence to get the next ID number.
I've been doing SQL Server for years and know several ways to do it there but none are helping me here.
I've tried using
SELECT * FROM user_source
WHERE UPPER(text) LIKE '%blah%'
Results are returned but only for my default schema and not for the schema I need to be searching in.
I also tried the below but it just errors
SELECT * FROM SchemaName.user_source
WHERE UPPER(text) LIKE '%blah%'
SELECT * FROM ALL_source WHERE UPPER(text) LIKE '%BLAH%'
EDIT Adding additional info:
SELECT * FROM DBA_source WHERE UPPER(text) LIKE '%BLAH%'
The difference is dba_source will have the text of all stored objects. All_source will have the text of all stored objects accessible by the user performing the query. Oracle Database Reference 11g Release 2 (11.2)
Another difference is that you may not have access to dba_source.
I allways use UPPER(text) like UPPER('%blah%')
If you use UPPER(text), the like '%lah%' will always return zero results. Use '%LAH%'.
For me, the given query didn't work. It was showing no result. I really don't know why. But "Dependancy" feature of SQLDeveloper saved my day!!!.
In SQLDeveloper, when you select the table in lefthand side "connection" view, tables details opened in the "document" view on righthand side. There are many tabs in document view like columns, data, model, constrain etc. One of the tab is "Dependancy". This tabs list all the objects like triggers, indexes, functions, procedures etc where table is refered.
For TOAD, I think, it is "Referantial" and "Used By" tabs. (Not sure about it, please refer TOAD referrance materials)
Hope this will help someone who is struggling with query like me.