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)
Related
I know UDF in legacy sql, but UDF need you pass whole row into function, and return whole record, and UDF can't put into select section, this is not real function I need, Is Bigquery Legacy SQL can write function like Standard SQL? (can put into select or where section)
thanks :)
This functionality is only supported in Standard SQL (and as Elliott mentions in the comments, is unlikely to be added to Legacy SQL because it is being phased out).
I had understood that jOOQ would simulate SQL MERGE on systems (such as PostgreSQL) that don't support it.
I have a table with a serial (autoincrement) "id" column and a string "uri" column. I want to use numeric IDs instead of URIs in my database, so I have to make sure I have a URI in the ID lookup table. So following the example in the jOOQ manual, I thought this would work:
createDSLContext().mergeInto(tableByName("uris"))
.using(createDSLContext().selectOne())
.on(fieldByName("uri").equal("http://example.com/"))
.whenNotMatchedThenInsert(fieldByName("uri"))
.values("http://example.com/").execute();
This gives me a DataAccessException saying something like:
SQL [merge into "uris" using (select 1) on "uri" = ? when not matched then insert ("uri") values (?)]; ERROR: syntax error at or near "merge"
But then the log says jOOQ goes ahead and tries to execute the query with bind values. But the table is never updated. So I'm guessing the jOOQ doesn't simulate MERGE on PostgreSQL?
So I then try the H2 database syntax:
createDSLContext().mergeInto(tableByName("uris"), fieldByName("uri")).values(uri.toString()).execute();
I get:
The H2-specific MERGE syntax is not supported in dialect : POSTGRES
What!? But the jOOQ documentation says that the H2 syntax "can be fully simulated by jOOQ for all other databases that support the SQL standard." Surely PostgreSQL supports the SQL standard. Does it really mean "...the SQL standard version of MERGE?"
Is there any way to get PostgreSQL support for MERGE via jOOQ, or am I stuck doing the same workarounds I would do anyway?
To be sure if a given SQL feature is supported by jOOQ for your database, please consider the Javadoc's #Support annotation on the relevant DSL method. This is also documented in the manual. In this case, DSLContext.mergeInto(), where you can see that this statement is currently only supported for these SQLDialects:
#Support(value={CUBRID,DB2,HSQLDB,ORACLE,SQLSERVER,SYBASE})
MERGE is a very powerful statement that is not really easy to emulate if your database doesn't natively support it.
"can be fully simulated by jOOQ for all other databases that support the SQL standard." Surely PostgreSQL supports the SQL standard. Does it really mean "...the SQL standard version of MERGE?"
Yes of course, the SQL standard MERGE statement must be supported :-) We'll clarify this in the manual. I have registered issue #3183 for this.
Is there any way to get PostgreSQL support for MERGE via jOOQ, or am I stuck doing the same workarounds I would do anyway?
Right now, unfortunately, we don't have a solution for this in PostgreSQL. Feel free to discuss possible solutions on the jOOQ User Group.
Yes , it can support which database support the merge in SQL stand.
but postgresql unsupport this feature in SQL standard.
Please see
F312 MERGE statement
F313 Enhanced MERGE statement
F314 MERGE statement with DELETE branch
http://www.postgresql.org/docs/9.3/static/unsupported-features-sql-standard.html
I have a SqlServer db that I would like to port to MySQL. What's the best way to to this. Things that need to be ported are:
Tables (and data)
FileStream → MySQL equivalent?
Stored Procedures
Functions
Data types are relatively similar.
There is no equivalent to FileStream in MySQL - the files must either be stored as BLOBs, or on the file system while the path is stored in the database.
Migrating away from TSQL means:
There's no WITH clause in MySQL - it will have to converted into a derived table/inline view
There's no TOP syntax - these have to be converted to use LIMIT
There's no ranking/analytic functionality in MySQL - can't use ROW_NUMBER, RANK, DENSE_RANK or NTILE. See this article for alternatives.
MySQL views have notoriously limited functionality:
The SELECT statement cannot contain a subquery in the FROM clause.
The SELECT statement cannot refer to system or user variables.
Within a stored program, the definition cannot refer to program parameters or local variables.
The SELECT statement cannot refer to prepared statement parameters.
Any table or view referred to in the definition must exist. However, after a view has been created, it is possible to drop a table or view that the definition refers to. In this case, use of the view results in an error. To check a view definition for problems of this kind, use the CHECK TABLE statement.
The definition cannot refer to a TEMPORARY table, and you cannot create a TEMPORARY view.
Any tables named in the view definition must exist at definition time.
You cannot associate a trigger with a view.
As of MySQL 5.0.52, aliases for column names in the SELECT statement are checked against the maximum column length of 64 characters (not the maximum alias length of 256 characters).
Dynamic SQL will have to be converted to use MySQL's Prepared Statement syntax
A guide/article with some useful tips is available on the official MySQL dev site.
This is not for the faint of heart. Here is an article that explains what you are in for:
http://searchenterpriselinux.techtarget.com/news/column/0,294698,sid39_gci1187176,00.html
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!
As the topic suggests I wish to be able to pass table names as parameters using .NET (doesn't matter which language really) and SQL Server.
I know how to do this for values, e.g. command.Parameters.AddWithValue("whatever", whatever) using #whatever in the query to denote the parameter. The thing is I am in a situation where I wish to be able to do this with other parts of the query such as column and table names.
This is not an ideal situation but it's one I have to use, it's not really prone to SQL injection as only someone using the code can set these table names and not the end-user. It is messy however.
So, is what I am asking possible?
EDIT: To make the point about SQL injection clear, the table names are only passed in by source code, depending on the situation. It is the developer who specifies this. The developer will have access to the database layer anyway, so the reason I am asking is not so much for security but just to make the code cleaner.
You cannot directly parameterize the table name. You can do it indirectly via sp_ExecuteSQL, but you might just as well build the (parameterized) TSQL in C# (concatenating the table-name but not the other values) and send it down as a command. You get the same security model (i.e. you need explicit SELECT etc, and assuming it isn't signed etc).
Also - be sure to white-list the table name.
I don't think I've ever seen this capability in any SQL dialect I've seen, but it's not an area of expertise.
I would suggest restricting the characters to A-Z, a-z, 0-9, '.', '_' and ' ' - and then use whatever the appropriate bracketing is for the database (e.g. [] for SQL Server, I believe) to wrap round the whole thing. Then just place it directly in the SQL.
It's not entirely clear what you meant about it not being a SQL injection risk - do you mean the names will be in source code and only in source code? If so, I agree that makes things better. You may not even need to do the bracketing automatically, if you trust your developers not to be cretins (deliberately or not).
You can pass the table name as a parameter like any other parameter. the key is you have to build a dynamic sql statement, which then you should consider if it's easier to build it in your app tier or in the procs.
create procedure myProc
#tableName nvarchar(50)
as
sp_executesql N'select * from ' + #tablename
fyi this code sample is from memory have a look at BOL for the proper syntax of sp_executesql.
Also this is highly sucesptible to SQL injection as you indicated is not an issue for you but anyone reading this should be very wary of accepting input from a user to generate their queries like this.
SQL query parameters can only take the place of a literal value. You cannot use a parameter for a table name, column name, list of values, or other SQL syntax. That's standard SQL behavior across all brands of database.
The only way to make the table name dynamic is to interpolate a variable into your SQL query before you prepare that string as a statement.
BTW, you're fooling yourself if you think this isn't a risk for SQL injection. If you interpolate the table name into the query dynamically, you need to use delimited identifiers around the table name, just as you would use quotes around a string literal that is interpolated from a variable.
The idea that it is not prone to SQL injection is misguided. It may be less prone to SQL injection from front end users, but it is still very much prone to SQL injection. Most attacks on databases come from inside the company being attacked, not from end users.
Employees may have grudges, they may be dishonest, they may be disgruntled, or they may just be not so bright and think that it's ok to bypass security to do whatever it is that THEY think should be done to the database.
Please see this post answer by user Vimvq1987:
MySqlParameter as TableName
Essentially you first check the table name against the schema, in which the table name is used in a parameterized fashion. Then if all is ok, the table name is legit.
Paraphrased basic idea is:
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'databasename'
AND table_name = #table;
cmd.Parameters.AddWithValue("#table",TableName);
If this returns ok with the table name, go ahead with your main query...
I would just check
select OBJECT_ID(#tablename)
the idea is to prevent injection you know it has to be table name this was if this returns a number then i would run the actual query,