How does the "With" keyword work in SQL? - sql

So many times seen with and, so many times SQL Server ask that with has ; before it
How does ;with ... work??
;with coords(...) as (
SELECT * ...
)
Why must have ; before it?

The semicolon is used in SQL to end a query. Putting it before a query like that is just to make sure that the database understands that any previous query has ended.
Originally it was required after each query as they were entered line by line, so the database had to know when to run the query. When the entire query is sent in a single string, you only need semicolons in the case where the SQL syntax is not enough to determine where a query ends. As the with keyword has different uses a semicolon is sometimes needed before it to make sure that it's not part of the previous query.

Using WITH for CTEs requires the previous statement to be terminated with ;. Using it at the start like this guarantees correct syntax
So does MERGE in SQL Server 2008
See this SO question: Incorrect syntax near the keyword 'with'...previous statement must be terminated with a semicolon

It is best practise to terminate every SQL statement with a semicolon. The SQL Server docs (for example here) suggest doing so will be mandated in a future version to there's really no excuse for not getting into the habit now.
To answer the question: you see ;WITH... on Stackoverflow because EITHER the person answering is a sloppy coder OR the person answering assumes the person asking the question is a sloppy coder (and they'll claim it is the latter when it is the former :) The definition of "sloppy coder" here is someone who only uses a semicolon when they are forced to do so.

The use of WITH is for common table expressions (CTEs). They were trying to force the CTE to be defined as the first statement (i.e. cannot be linked with other parts of the query hence the ;)

Related

Syntax error in INSERT INTO statement

I am trying to insert some information in an MS Access database.
In my database I have the following columns and types:
log_order - Autonumber (I need this to keep the order where inserted in the db),
userID - Text,
time - Text,
date_ - text,
message - Text.
My query:
command.CommandText = "INSERT INTO logs(userID, time, date_, message) VALUES ('"+verifiedUser+"', '"+msg_time+"', '"+msg_date+"', '"+msg+"')";
OleDbDataReader reader = command.ExecuteReader();
The error that I get:
System.Data.OleDb.OleDbException: 'Syntax error in INSERT INTO statement.'
I tried several posts but no post helped me. I believe there might be a problem with the autonumber column (log_order). Because of what I remember I don't have to include it in the query.
PS: I know I have to pass the values as parameters.
Thank you in advance
Probably one of your variables (msg?) contains an apostrophe
The way you've written your SQL is a massive security risk. Please immediately look up "parameterized queries" and never, ever, ever write an sql like this again (where you use string concatenation to tack the values into the query). Your code has a proliferation of issues and using parameterized queries will solve all of them; they aren't difficult to write
It seems your data in some of the variables passed in INSERT may be causing this error. Try debugging the value in command.CommandText before executing it.
If any of the variables have a single quote they must be escaped...
Ref: How do I escape a single quote in SQL Server?
Also brush up on SQL Injection Ref: SQL Injection
I totally agree with all that has been said, but to answer your question directly, I am pretty sure you will need to put square brackets around your field names. OleDb tends not to like special characters and could well be having a problem for example with date_ ; sending [date_] instead should get round the issue.
It will not like time either. Same solution
Addendum on SQL Injection
As an aside, in fact calling Access through OleDb is relatively protected from SQL Injection. This is because any attempt to execute multiple instructions in one command fails. (You get an incorrect formatted string error). So whilst you could argue that what you are doing is safe, it is not for other db providers. The sooner you get into good habits, the less likely you will be to introduce a vulnerability in a case where it could be dangerous. If it seems like you are getting a stream of abuse, it is just because everyone here wants to keep the net safe.

visual studio 2012 query builder

Can anybody tell me what does the error mean? Whenever I open the query builder it will prompt with an error indicating that SQL syntax errors were encountered.
https://msdn.microsoft.com/en-us/library/ms189012.aspx
I looked at the following page in MSDN but I don't understand what it means...
For instance, what do these bullet points from the MSDN article mean?
The SQL statement is incomplete or contains one or more syntax errors.
The SQL statement is valid but is not supported in the graphical panes (for example, a Union query).
The SQL statement is valid but contains syntax specific to the data connection you are using.
USER (which you've apparently decided is an appropriate table name) is a SQL Server reserved word.
The best solution is to rename your table, so you don't have to escape the table name every time you want to query it and to make it clear it's your user data (hey, there's a table name suggestion - userdata).
The other option is to escape the name by surrounding it with square brackets:
SELECT * FROM [users]
Note that it will get old fast having to do this with every query. Again, the best solution would be to rename the table to something that isn't a reserved word.

SQL Command ISNULL for ODBC Connection

I'm connected to an OpenEdge DataServer via ODBC (not our product, we are just accessing their database, I hardly have any information and certainly no help from the other side).
Anyhow, I just need to execute a simple Select, add a couple of rows and I need the equivalent of an IsNull statement.
Basically I'd like to execute
SELECT ISNULL(NULL,'test')
This fails with a Syntax Error. I've looked around at something they misleadingly call a "documentation" but there are only references to SP_SQL_ISNULL but I can't get that to work either. I'm fit in T-SQL, so any pointers in any direction appreciated, even if it's just a RTFM with a link to TFM :)
Thanks
Thanks to Catalin and this question I got on the right track. I kept thinking I needed a OpenEdge specific function but actually I needed to use only ODBC SQL syntax.
To get what
ISNULL(col,4)
does you can use
COALESCE(col,4)
which "returns the data type of expression with the highest data type precedence. If all expressions are nonnullable, the result is typed as nonnullable."MSDN
Basically it will convert to 4 if the value is null (and therefore not convertable).
I am not 100% sure, but I think ODBC driver expects a valid SQL statement, and not an DBMS specific SQL statement, like the one you provided.

INSERT vs INSERT INTO

I have been working with T-SQL in MS SQL for some time now and somehow whenever I have to insert data into a table I tend to use syntax:
INSERT INTO myTable <something here>
I understand that keyword INTO is optional here and I do not have to use it but somehow it grew into habit in my case.
My question is:
Are there any implications of using INSERT syntax versus INSERT INTO?
Which one complies fully with the standard?
Are they both valid in other implementations of SQL standard?
INSERT INTO is the standard. Even though INTO is optional in most implementations, it's required in a few, so it's a good idea to include it if you want your code to be portable.
You can find links to several versions of the SQL standard here. I found an HTML version of an older standard here.
They are the same thing, INTO is completely optional in T-SQL (other SQL dialects may differ).
Contrary to the other answers, I think it impairs readability to use INTO.
I think it is a conceptional thing: In my perception, I am not inserting a row into a table named "Customer", but I am inserting a Customer. (This is connected to the fact that I use to name my tables in singular, not plural).
If you follow the first concept, INSERT INTO Customer would most likely "feel right" for you.
If you follow the second concept, it would most likely be INSERT Customer for you.
It may be optional in mySQL, but it is mandatory in some other DBMSs, for example Oracle. So SQL will be more potentially portable with the INTO keyword, for what it's worth.
In SQL Server 2005, you could have something in between INSERT and INTO like this:
INSERT top(5) INTO tTable1 SELECT * FROM tTable2;
Though it works without the INTO, I prefer using INTO for readability.
One lesson I leaned about this issue is that you should always keep it consistent! If you use INSERT INTO, don't use INSERT as well. If you don't do it, some programmers may ask the same question again.
Here is my another related example case: I had a chance to update a very very long stored procedure in MS SQL 2005. The problem is that too many data were inserted to a result table. I had to find out where the data came from. I tried to find out where new records were added. At the beginning section of SP, I saw several INSERT INTOs. Then I tried to find "INSERT INTO" and updated them, but I missed one place where only "INSERT" was used. That one actually inserted 4k+ rows of empty data in some columns! Of course, I should just search for INSERT. However, that happened to me. I blame the previous programmer IDIOT:):)
They both do the same thing. INTO is optional (in SQL Server's T-SQL) but aids readability.
I started wtiting SQL on ORACLE, so when I see code without INTO it just looks 'broken' and confusing.
Yes, it is just my opinion, and I'm not saying you should always use INTO. But it you don't you should be aware that many other people will probably think the same thing, especially if they haven't started scripting with newer implementations.
With SQL I think it's also very important to realise that you ARE adding a ROW to a TABLE, and not working with objects. I think it would be unhelpful to a new developer to think of SQL table rows/entries as objects. Again, just me opinion.
INSERT INTO is SQL standard while INSERT without INTO is not SQL standard.
I experimented them on SQL Server, MySQL, PostgreSQL and SQLite as shown below.
Database
INSERT INTO
INSERT
SQL Server
Possible
Possible
MySQL
Possible
Possible
PostgreSQL
Possible
Impossible
SQLite
Possible
Impossible
In addition, I also experimented DELETE FROM and DELETE without FROM on SQL Server, MySQL, PostgreSQL and SQLite as shown below:
Database
DELETE FROM
DELETE
SQL Server
Possible
Possible
MySQL
Possible
Impossible
PostgreSQL
Possible
Impossible
SQLite
Possible
Impossible
I prefer using it. It maintains the same syntax delineation feel and readability as other parts of the SQL language, like group BY, order BY.
If available use the standard function. Not that you ever need portability for your particular database, but chances are you need portability for your SQL knowledge.
A particular nasty T-SQL example is the use of isnull, use coalesce!

How do I deal with quotes ' in SQL [duplicate]

This question already has answers here:
How to anticipate and escape single quote ' in oracle
(2 answers)
Closed 7 years ago.
I have a database with names in it such as John Doe etc. Unfortunately some of these names contain quotes like Keiran O'Keefe. Now when I try and search for such names as follows:
SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe'
I (understandably) get an error.
How do I prevent this error from occurring. I am using Oracle and PLSQL.
The escape character is ', so you would need to replace the quote with two quotes.
For example,
SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe'
becomes
SELECT * FROM PEOPLE WHERE SURNAME='O''Keefe'
That said, it's probably incorrect to do this yourself. Your language may have a function to escape strings for use in SQL, but an even better option is to use parameters. Usually this works as follows.
Your SQL command would be :
SELECT * FROM PEOPLE WHERE SURNAME=?
Then, when you execute it, you pass in "O'Keefe" as a parameter.
Because the SQL is parsed before the parameter value is set, there's no way for the parameter value to alter the structure of the SQL (and it's even a little faster if you want to run the same statement several times with different parameters).
I should also point out that, while your example just causes an error, you open youself up to a lot of other problems by not escaping strings appropriately. See http://en.wikipedia.org/wiki/SQL_injection for a good starting point or the following classic xkcd comic.
Oracle 10 solution is
SELECT * FROM PEOPLE WHERE SURNAME=q'{O'Keefe}'
Parameterized queries are your friend, as suggested by Matt.
Command = SELECT * FROM PEOPLE WHERE SURNAME=?
They will protect you from headaches involved with
Strings with quotes
Querying using dates
SQL Injection
Use of parameterized SQL has other benefits, it reduces CPU overhead (as well as other resources) in Oracle by reducing the amount of work Oracle requires in order to parse the statement. If you do not use parameters (we call them bind variables in Oracle) then "select * from foo where bar='cat'" and "select * from foo where bar='dog'" are treated as separate statements, where as "select * from foo where bar=:b1" is the same statement, meaning things like syntax, validity of objects that are referenced etc...do not need to be checked again. There are occasional problems that arise when using bind variables which usually manifests itself in not getting the most efficient SQL execution plan but there are workarounds for this and these problems really depend on the predicates you are using, indexing and data skew.
Input filtering is usually done on the language level rather than database layers.
php and .NET both have their respective libraries for escaping sql statements. Check your language, see waht's available.
If your data are trustable, then you can just do a string replace to add another ' infront of the ' to escape it. Usually that is enough if there isn't any risks that the input is malicious.
I suppose a good question is what language are you using?
In PHP you would do: SELECT * FROM PEOPLE WHERE SURNAME='mysql_escape_string(O'Keefe)'
But since you didn't specify the language I will suggest that you look into a escape string function mysql or otherwise in your language.
To deal quotes if you're using Zend Framework here is the code
$db = Zend_Db_Table_Abstract::getDefaultAdapter();
$db->quoteInto('your_query_here = ?','your_value_here');
for example ;
//SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe' will become
SELECT * FROM PEOPLE WHERE SURNAME='\'O\'Keefe\''
Found in under 30s on Google...
Oracle SQL FAQ