I want to check the syntax of a SQL query. I thought to do in preparing it, with DbCommand.Prepare method.
Unfortunately, no error or exception.
For example: SELECT * FORM table
Is there a way to check the syntax without executing the query ?
To make it perfect, it has to work on SQL Server, Oracle and IBM DB2
For SQL Server, you can use SET FMTONLY and/or SET NOEXEC
set fmtonly on
go
SELECT * FORM table
go
set fmtonly off
Generally only the database you're using is going to know whether a given query is valid or not. One standard and portable trick is to add a WHERE clause that guarantees nothing will be done, then execute the query; for example execute SELECT * FORM table WHERE 1=0 and see what happens.
Related
I have access to an Access database and within that database are fields filled with TSQL queries. These queries are processed by T-SQL on a server. So when I write these SQL queries and put them into a field for use by the end server, I'm unable to validate the syntax/etc. I could create a temporary query in that Access database, but it's not the same query language. For example, Access would correctly use IIF but TSQL would not (it would instead be CASE).
I don't have direct access to this server with TSQL, is there a way I can validate my T-SQL queries (for syntax and the like)? Perhaps a web tool online?
I should note I do not have access to the SQL server. Only the Access db and that alone. I understand it will not validate table names and the like, I wouldn't expect it to.
Actually, a combination of MattMc3's answer and FremenFreedom's answer should work.
Download SQL Express.
Then, declare the following stored procedure:
create procedure IsValidSQL (#sql varchar(max)) as
begin
begin try
set #sql = 'set parseonly on;'+#sql;
exec(#sql);
end try
begin catch
return(1);
end catch;
return(0);
end; -- IsValidSQL
You can test it with:
declare #retval int;
exec #retval = IsValidSQL 'select iif(val, 0, 1) from t';
select #retval
or with:
declare #retval int;
exec #retval = IsValidSQL 'select val from t';
select #retval
Note: this will catch the IIF() issue. It will not catch anything related to the table structures or column structures. You would need the schema for that and a slightly different approach ("select top 0 * from () t") woudl do it.
You might be able to do something with SQL Fiddle online. However, I would suggest having a local copy of the database.
You can parse your T-SQL to check for valid syntax by executing it on the SQL Server machine with a SET PARSEONLY ON as the first line of your script. It will not validate table or field names, but will provide you with any syntax errors.
The Data Dude (Gert Drapers) describes how to use the built-in SQL Server T-SQL parser in your application here:
Getting to the Crown Jewels
If you want to only check the validity of the SQL statements that you have - this might be a nice way to go, and it doesn't require SQL Server per se to be installed where you run your unit tests.
It's a .NET based approach, and it cannot - of course - validate object names in your database if you're not using a live database - but it can catch syntactical errors in your T-SQL statements.
You can use the NOEXEC option:
SET NOEXEC ON
SELECT 1 AS Test
SET NOEXEC OFF
Is SQL Server Management Studio Express (free download) able to connect to regular SQL Server instances? If so, perhaps you could test the queries there. Even if you could not connect to the actual server, you might be able to create a test version of your database in Express that would at least allow you to catch syntax and naming problems.
If they are fairly static, convert them into stored procedures in the Sql Database and then just call them from access.
I have little to no experience with TSQL and SQL Server - so in MySQL when I want to execute a statement I simply write:
Select * from users
...and then hit ENTER.
However now I see many SQL Server tutorials that you have the GO word immediately after each statement. Do I have to write this? For example:
Select * from users; GO
Or I can simply write:
Select * from users; <enter key pressed...>
In SQL Server, go separates query batches. It's optional in most situations.
In earlier versions of SQL Server, you had to do a go after altering a table, like:
alter table MyTable add MyColumn int
go
select MyColumn from MyTable
If you didn't, SQL Server would parse the query batch, and complain that MyColumn didn't exist. See MSDN:
SQL Server utilities interpret GO as a
signal that they should send the
current batch of Transact-SQL
statements to an instance of SQL
Server. The current batch of
statements is composed of all
statements entered since the last GO,
or since the start of the ad hoc
session or script if this is the first
GO.
GO separates batches, as Andomar wrote.
Some SQL statements (e.g. CREATE SCHEMA) need to be the first or only statements within a batch. For example, MSDN states
The CREATE PROCEDURE statement cannot
be combined with other Transact-SQL
statements in a single batch.
Local variables are also limited to a batch, and therefore are not accessible after a GO.
Go is optional, no need to write that in your sql statements.
You don't have to. What the GO will do is execute each statement (at least in Sql Server)
As the other answerers said before me, you don't really NEED Go.
There is only one case when you have to use it, and that's when you want to create a table or view and then select from it.
For example:
create view MyView as select * from MyTable
go
select * from MyView
Without Go, Sql Server won't execute this because the select statement is not valid, because the view doesn't exist at that moment.
i want to check select statement(string) is valid or not in c#.net, if select statement is right then retrieve data and fill dropdown list box else drop down should be empty
How often would the select statement be invalid? Seems like a simple try/catch block around the execution of the SQL might be sufficient.
As an aside, I hope you aren't making an app that would allow someone to type in arbitrary SQL into a box which you would then execute...
One approach which covers most scenarios is to execute the SQL with SET FMTONLY ON
e.g.
SET FMTONLY ON;
SELECT SomeField FROM ExampleQuery
From BOL, SET FMTONLY :
Returns only metadata to the client.
Can be used to test the format of the
response without actually running the
query.query.
That will error if the query is invalid. You can also check the result to determine what the schema of the resultset that is returned would be (i.e. no schema = not a SELECT statement).
Update:
In general terms when dealing with SQL that you want to protect against SQL injection there are other things you should be thinking about:
Avoid dynamic sql (concatenating user-entered values into an SQL string to be executed). Use parameterised SQL instead.
Encapsulate the query as a nested query. e.g.
SELECT * FROM (SELECT Something FROM ADynamicQueryThatsBeenGenerated) x
So if the query contains multiple commands, this would result in an error. i.e. this would result in an invalid query when encapsulated as a nested query:
SELECT SomethingFrom FROM MyTable;TRUNCATE TABLE MyTable
Is there a standard way to simulate a table creation in a database by using SQL? I don't want the table to be created, just check if it could be created.
One way would be to create it and then delete it again.
Any other way?
Most major servers support transactional DDL, so you can do something along these lines:
begin transaction
create table Foo ...
rollback transaction
Theoretically, in case of error it should be reported back to client, but table will not be created altogether.
Depends on the SQL DBMS you're interested in. For example Postgres supports transactional DDL and the following will work:
START TRANSACTION;
CREATE TABLE ... ();
<check for error here>
ROLLBACK;
If you're using MySQL, you could create it using a transient storage engine, like MEMORY .
Really, you have to actually create it to make sure everything is OK.
Foreign key references, functions used as default or check constraints or in computed columns are not checked until execute time.
One basic method (SQL Server) is to use "SET FMTONLY ON".
Useful for checking the statement is valid, though won't tell you everything (e.g. if the table already exists).
This will succeed:
SET FMTONLY ON
EXECUTE ('CREATE TABLE SomeTable(SomeField INTEGER)')
SET FMTONLY OFF
This will not:
SET FMTONLY ON
EXECUTE ('CREATE TABLE SomeTable(dodgysyntax)')
SET FMTONLY OFF
This approach is probably more useful for SELECT statements, which is what I've used it for in the past. It doesn't actually execute the statement, but returns out the metadata.
I was writing a (seemingly) straight-forward SQL snippet that drops a column after it makes sure the column exists.
The problem: if the column does NOT exist, the code inside the IF clause complains that it can't find the column! Well, doh, that's why it's inside the IF clause!
So my question is, why does a piece of code that shouldn't be executed give errors?
Here's the snippet:
IF exists (select * from syscolumns
WHERE id=object_id('Table_MD') and name='timeout')
BEGIN
ALTER TABLE [dbo].[Table_MD]
DROP COLUMN timeout
END
GO
...and here's the error:
Error executing SQL script [...]. Invalid column name 'timeout'
I'm using Microsoft SQL Server 2005 Express Edition.
IF exists (select * from syscolumns
WHERE id=object_id('Table_MD') and name='timeout')
BEGIN
DECLARE #SQL nvarchar(1000)
SET #SQL = N'ALTER TABLE [dbo].[Table_MD] DROP COLUMN timeout'
EXEC sp_executesql #SQL
END
GO
Reason:
When Sql server compiles the code, they check it for used objects ( if they exists ). This check procedure ignores any "IF", "WHILE", etc... constructs and simply check all used objects in code.
It may never be executed, but it's parsed for validity by Sql Server. The only way to "get around" this is to construct a block of dynamic sql and then selectively execute it
Here's how I got it to work:
Inside the IF clause, I changed the ALTER ... DROP ... command with exec ('ALTER ... DROP ...')
It seems the SQL server does a validity check on the code when parsing it, and sees that a non-existing column gets referenced somewhere (even if that piece of code will never be executed).
Using the exec(ute) command wraps the problematic code in a string, the parser doesn't complain, and the code only gets executed when necessary.
Here's the modified snippet:
IF exists (select * from syscolumns
WHERE id=object_id('Table_MD') and name='timeout')
BEGIN
exec ('ALTER TABLE [dbo].[Table_MD] DROP COLUMN timeout')
END
GO
By the way, there is a similar issue in Oracle, and a similar workaround using the "execute immediate" clause.