Identify DBMS from dialect SQL syntax? - sql

I'm working with a third party API for which I have no documentation. There is a method that takes a SQL string and returns a resultset. Based on valid SQL syntax, I want to identify the SQL DBMS vendor, product and version.
Syntax that works as expected as part of a valid SELECT query:
CASE WHEN 1 = 1 THEN 1 ELSE 0 END
CAST('Catatonic' AS CHAR(3))
GETDATE()
CONVERT(VARCHAR(10), GETDATE(), 101))
SELECT TOP 1 valid_column FROM ValidTable
Syntax that causes syntax errors:
COALESCE(NULL, 'Dog')
ISNULL(NULL, 'Dog')
CURRENT_TIMESTAMP
SELECT ##VERSION
SELECT version()
statements terminated by ; (though this could be an API thing)
Any other SQL syntax to try?

My attempt at an answer, given your tests and the comments above:
Tell the 3rd-party that hosts the API, as well as your boss and/or customer, that you cannot work with an API that does not have documentation, and you MUST have further support from the API vendor to perform your work effectively.
If the documentation says "ANSI SQL Compliant", then that is obviously not true, since your tests include various (well thought-out) instances that would seem to suggest SQL Server, but obviously do not support all queries that SQL Server itself would allow.
So, the 3rd party is apparently filtering, re-parsing, or otherwise modifying the SQL you provide to it, and without further information about what that layer is and what it does/doesn't do, you're hands are more or less tied, and your limited to guesswork and trial-and-error.

Related

Compatibility of "column as alias" vs "alias = column"

I've found that over the years my habits have changed and I much prefer writing queries like this:
select FriendlyName = some_column from some_table
as opposed to this:
select some_column as FriendlyName from some_table
Lately I've been reviewing scripts written by some SQL experts which were designed to work across multiple database versions and platforms and I only ever see the latter syntax.
This was never a concern for me before as a software developer knowing specifically what version of SQL Server my code would be run on, but now I'm writing code that I would like to make as accessible to as many versions/platforms as possible. At least, I'd like to write it so the least amount of modifications are necessary to run on additional versions when the time comes.
That said, my question is whether the former syntax (alias = some_column) has always been part of the SQL specification and will run on any database, or would it not work in some platforms or older versions?
The alias = syntax is specific to SQL Server. The standard is either:
<expression> as alias
<expression> alias
That is, the as is optional -- although I strongly encourage using it.
It is a shame that you have adapted to a syntax that is not available in other databases, and can actually mean other things. In most other databases that accept the syntax, it will be interpreted as a boolean comparison -- and often generate an error because alias is not defined.
And, unfortunately, this syntax convention makes it harder to SQL Server to support a real boolean type, which would be a convenience.

Is SELECT INTO T-SQL?

I'm working in a project where I have been explicitly required to not use T-SQL syntax. The application we are using supports T-SQL but we are not allowed to use it to avoid potential migration issues.
My question is: is the SELECT ... INTO statement T-SQL or SQL? If it is T-SQL, is there a specific SQL query to copy an existing table into a new one? (I have tried with CREATE TABLE AS .. FROM but it doesn't work).
Sounds like a very basic question but I haven't been able to find the answer anywhere. Thus, in addition to the question above, it would be very helpful to know if there is a guide/dictionary/website that collects only the standard SQL syntax.
Thanks!
I think they recommend you to use ANSI SQL, instead of T-SQL (SQL Server) or PL-SQL (ORACLE). Considering it as common requirement, every database vendor provide their own way of implementing this requirement. When you use ANSI SQL, you will not have migration issues, when you move from one database vendor to another database vendor.
SQL SERVER
SELECT * INTO new_table
FROM existing_table
ORACLE & ANSI-SQL
CREATE TABLE new_table
AS SELECT * FROM existing_table
is SELECT INTO TSQL or SQL?
Neither. The MySQL documentation claims that SELECT INTO is a Sybase extension to standard sql. As such I don't think you can accurately say it's either of these, but you can say that it's neither. It is indeed used in T-SQL, as well as some other database vendor products, to create a table from a query. The SQL standard says that queries with that goal should be formed as CREATE TABLE blah AS SELECT .... Oracle/MySQL, for example, use the standard form though you can see them use SELECT INTO in a different context, to assign data to variables in stored procedures
If you want to avoid use of this non standard syntax when creating and populating a table then you'll have to:
CREATE TABLE blah (column spec to match query output)
INSERT blah (select query here)
But then you run into nuances like "sqlserver calls it datetime/datetime2 but oracle calls it date/timestamp"
And ultimately you'll probably get into a situation where you just can't use one form of sql to do all you want..
I'd imagine most libraries that do data access on multiple underlying databases have mechanisms to use vendor specific terminology where required
From the answers, it appears you might need to specify which SELECT INTO you're talking about. The other answers seem to suggest there exists some kind of SELECT ... INTO <table-name> when there is also a kind of SELECT ... INTO <local-variable-name list>. The latter is used in embedded SQL for making SQL interact with variables of the host language program. I'm not certain but that variant may also be used in the part of the SQL language that deals with procedures written in SQL (the SQL/PSM part of the standard).
A "reference" that covers "only the standard SQL syntax" is, in principle, the ISO standard document itself, only available by purchase from ISO (and yes, it's ISO not ANSI - ANSI does nothing more than rubberstamping the ISO document after removing all the names of non-US contributors). And not the easiest kind of literature. There are "draft" versions floating around on the internet that might deviate from the published final standards. E.g. http://www.wiscorp.com/sql200n.zip. Note that this is a SQL:2008 draft. Current standard version is SQL:2011. And it's several thousands of pages, so I guess that covers your question "Is all the syntax covered in w3schools standard SQL". (Hint : no)

MS SQL Query to base SQL

I am looking to have the following query run on any database (right now it uses MSSQL):
SELECT * FROM mytable
WHERE 0<DATEDIFF(day, ISNULL(DateTwo, DateONE), getdate())
AND othercolumn != 'WUBAN'
Is there anyway to do this in a generic way?
No, there is no generic way to do this.
If you support different DB engines you have to execute the proper SQL statement for each engine. Date functions differ on the individual DB engines and for this particular query there is no generic solution that works on all systems.
If DateTwo and DateOne are parameters, then you are able to do the following calculation in your application:
DATEDIFF(day, ISNULL(DateTwo, DateONE), getdate())
and use the result in your query. If not, I can not see a way.

MS Access SQL Server DB - Query Syntax for CAST Function

I have converted an Access db (.mdb) to SQL Server. In the meantime I still need to use Access as a front end until new application forms are constructed. Can someone tell me what I might do to fix the situation where:
In Access 2007, a query such as:
SELECT *
FROM TransactionTotals
WHERE TransactionTotals.[Date]= Date()
ORDER BY TransactionTotals.EntryID DESC;
worked, however since the Date() function will not work with SQL Server, with help in a previous post the correct syntax is:
SELECT *
FROM TransactionTotals
WHERE TransactionTotals.[Date]= CAST(GETDATE() AS DATE)
ORDER BY TransactionTotals.EntryID DESC;
BUT! Although the code above will work in a direct SQL Server query (SQL Management Studio), it will be tossed out in Access with a Syntax Error response on the WHERE clause.
Can something be done in Access so I can still run my query bound forms.
I usually do exactly what you do, Access first before migration to SQL server. Access has some really weird syntax compared to server type databases especially when it comes to JOIN clauses and dates, GETDATE() only works on SQL Server, in Access, try this...
SELECT *
FROM TransactionTotals
WHERE TransactionTotals.[Date]= Format(NOW(),"General Date")
ORDER BY TransactionTotals.EntryID DESC;
Feel free to change the format of the date, with or without time.

Can you explain this SQL injection?

The website i worked was recently attempted to be hacked by the following SQL injection script
boys' and 3=8 union
select 1,
concat(0x232425,ifnull(`table_name`,0x30),char(9),ifnull(`table_rows`,0x30), char(9),0x252423),
3,4,5,6,7,8,9
from `information_schema`.`tables`
where table_schema=0x62646B3032 limit 44,1 -- And '8'='8
This injection returned the mysql table name. This was reported by the error reporting system on that website and we managed to fix that part however I am not able to understand what does the above injection mean?
Anyone can explain this?
Penuel
They're using a select from the Information Schema views in mysql server :
http://dev.mysql.com/doc/refman/5.0/en/information-schema.html
They use some clever hacks to rout out simple sql injection prevention techniques.
According to this the MySQL concat()
Returns the string that results from
concatenating the arguments. May have
one or more arguments. If all
arguments are nonbinary strings, the
result is a nonbinary string. If the
arguments include any binary strings,
the result is a binary string. A
numeric argument is converted to its
equivalent binary string form
So 0x232425 is converted to #$% which is simply added to the begining and end of the table_name field. Maybe just to make it easier for them to pull out the Table names later using Regex.
Later on the char(9) is equivalent to a tab as you can see here and is just there to format the output nicer.
The 3,4,5,6,7,8,9 is just there so that the columns match the boys table that they are performing the Union on.
This injection returned the mysql table name.
Do you mean that your website displayed the table name when you gave it this input, or that the query returns that when run from the mysql client? If it showed on your website, then the attacker has the ability to inject much more harmful queries. Check your data.