Getting error when trying to Rename multiple tables in SPROC in DB2 - sql

I've created a DB2 sql script that populates a static table and then does a rename to swap out the live table with the newly updated one. Its a fairly large SQL script so I'm only including the areas that Im having a an error on.
I'm getting the error: "[IBM][CLI Driver][DB2/NT64] SQL0104N An unexpected token "RENAME" was found following "D_HOLIDAY_LOG_OLD; ". Expected tokens may include: "TRUNCATE". LINE NUMBER=382. SQLSTATE=42601".
I suspect, its a syntax issue with the RENAME commands. If I need to add the whole query, I can. Thanks in advance
CREATE OR REPLACE PROCEDURE NSD_HOLIDAY_LOG_SPROC()
LANGUAGE SQL
SPECIFIC SP_NSD_HOLIDAY_LOG_SPROC
DYNAMIC RESULT SETS 1
BEGIN
COMMIT;
TRUNCATE TABLE TMWIN.NSD_HOLIDAY_LOG immediate;
DROP TABLE NSD_HOLIDAY_LOG_OLD;
RENAME TABLE TMWIN.NSD_HOLIDAY_LOG_LIVE TO NSD_HOLIDAY_LOG_OLD;
RENAME TABLE TMWIN.NSD_HOLIDAY_LOG TO NSD_HOLIDAY_LOG_LIVE;
RENAME TABLE TMWIN.NSD_HOLIDAY_LOG_OLD TO NSD_HOLIDAY_LOG;
END#

This is frequently asked.
As you are using static SQL in an SQL PL stored procedure, you must follow the documented rules for blocks of Compound SQL (Compiled) statements.
On of those rules is that static SQL has a restricted set of statements that can appear in such a block of code.
For example, with current versions of Db2-LUW, you cannot use any of the following statically (including rename table) :
ALTER , CONNECT,CREATE, DESCRIBE, DISCONNECT, DROP, FLUSH EVENT MONITOR, FREE LOCATOR, GRANT, REFRESH TABLE, RELEASE (connection only), RENAME TABLE, RENAME TABLESPACE, REVOKE, SET CONNECTION, SET INTEGRITY, SET PASSTHRU, SET SERVER OPTION ,TRANSFER OWNERSHIP
Other Db2 platforms (Z/OS, i-series) might have different restrictions but the same principle.
To achieve what you need you can use dynamic SQL instead of Static-SQL (as long as you understand the implications).
In other words, instead of writing:
RENAME TABLE TMWIN.NSD_HOLIDAY_LOG_LIVE TO NSD_HOLIDAY_LOG_OLD;
you could instead use:
execute immediate('RENAME TABLE TMWIN.NSD_HOLIDAY_LOG_LIVE TO NSD_HOLIDAY_LOG_OLD' );
or equivalent.
You can also use two statements, one to PREPARE and the other to EXECUTE , whichever suits the design. Refer to the documentation for execute immediate.
The same is true for other statements that your version of Db2 disallows in static compound-SQL (compiled) blocks (for example, DROP, or CREATE etc.).

Related

Why alter command is referred as DDL and not DML?

I was going through the different commands in SQL and I came across alter command which is referred as DDL (Data Definition Language). We can alter the column and values in it, so we can manipulate the data with this command so why does alter command is not referred as DML (Data Manipulation Language).
I have googled and I can not come across some good explanation, so please help me with this.
ALTER command is used to alter the structure of the database. And this is what DDL does i.e., DDL statements are used to define the database structure or schema.
Whereas DML statement is used to manage data within schema objects.
DDL - alter the schema.
This including creating tables, renaming columns, dropping views, etc. Such statements are DDL even though such might create (default value), alter (by conversion), or even lose (removed column) data as part of the process. Basically, any CREATE/DROP/ALTER command is DDL.
DML - alter the information/data within the schema; without updating the schema.
This includes DELETE and UPDATE statements.
Sometimes DDL and DML must be used together to correctly migrate a schema; but they are two distinct categories of SQL commands, and DML never causes the schema to be changed.
Cause ALTER command is not manipulating the data. It is used to change a definition of o column or table or other DB objects.
See
http://www.w3schools.com/sql/sql_alter.asp
The "data" is the data in the tables defined by the user via DDL. The "metadata" is the data in the tables pre-defined by the DBMS that describe the tables (themselves and those defined by the user). So DML manipulates data in user tables or (usually only) reads metadata from system tables while DDL defines (CREATEs, ALTERs, DROPs) user tables and as a side effect updates metadata in system tables.
The ALTER command can be both DDL and DML. I have known ALTER to be DDL over the past just like the majority of those who have responded to this. However, with MySQL 5.7.x you will see that soon after initializing the database with mysqld --initialize --console a default root user account and its corresponding password is created. You can access your database with this newly created root user account BUT there is absolutely nothing that you can do after logging in. The only SQL statement allowed at this stage is the ALTER statement. This is used to change the default password generated during initialization. The syntax is ALTER USER 'root'#'localhost' IDENTITIED BY 'new_password'; . This is the only statement that the database accepts. This modifies/updates/manipulates the data (password) in the users table. In this regard I have concluded that the ALTER statement can be both DDL and DML

Is there any major issue in using EXEC sp_rename '<source table name>', '<destination table name>'?

I recently used - EXEC sp_rename '<source table name>', '<destination table name>' to rename an existing table and want to execute the same on one of our live server. Is there any issue in using this procedure to rename a table?. I am asking this because one of our DBA says there will be problems in using this procedure on live server.
Is nothing referencing the table you're renaming? That would be the only instance where I would think renaming the table would not have an impact. If the table was not referenced by anything however, what would be the purpose of the table?
you can read more about sp_rename here:
http://msdn.microsoft.com/en-us/library/ms188351.aspx
Specifically note the following:
Renaming an object such as a table or column will not automatically
rename references to that object. You must modify any objects that
reference the renamed object manually. For example, if you rename a
table column and that column is referenced in a trigger, you must
modify the trigger to reflect the new column name. Use
sys.sql_expression_dependencies to list dependencies on the object
before renaming it.
There is no major issue with renaming the table using that procedure. The only thing you need to remember is that while that command is being executed, the locks that are applied on that table won't allow you to query the data, but that should only take only a couple of milliseconds, so you should be fine.
P.S. Don't forget to modify your views, procedures, functions etc :)
Below is the only caution as described inthe microsoft official web site.
Changing any part of an object name can break scripts and stored procedures. We recommend you do not use this statement to rename stored procedures, triggers, user-defined functions, or views; instead, drop the object and re-create it with the new name.
More details at : http://msdn.microsoft.com/en-us/library/ms188351.aspx
EXEC sp_rename is recommended only when we sure that all the depended SP, View function are not get affected. Make sureyou changed or deleted the depended objects.
Perhaps your DBA can share the details of his/her concerns. Renaming a table will of course be a breaking change for any objects that reference the table so you'll need to perform due diligence to ensure dependent objects are changed to use the new name. The rename operation will also require a short schema modification lock and void existing referencing cached plans, so be aware of this if the table is heavily used.

In SQL, is 'FROM' in 'DELETE FROM' optional if you plan to use 'WHERE'?

I'm new to SQL. We have some code that should work on SQL Server 2005/2008, Oracle 10 as well as Sybase.
I was writing a script to try to figure out which tables a given stored procedure modifies (but does not drop), e.g insert, update and delete.
The delete one turned out being puzzling - sometimes I see statements like:
delete phone_book where ...
as opposed to:
delete from phone_book where ...
So ... is the from keyword truly optional in this case? Does this cause any problems? Is it just a bad style, or does it not matter?
I have not found a reference to T-SQL that would make from optional. I suppose that this is what would unify all 3 vendors I mentioned above.
Questions/comments/links are welcomed (or is it welcome?).
At this place the FROM is optional (SQL Server, Oracle, Sybase).
However, there are subtle differences: Oracle for instance allows assigning an alias to the table name, where SQL Server doesn't; and other things are also a little bit different.
Also note that your FROM sample is differnet from the following where it is mandatory:
DELETE phone_book FROM some_table WHERE ...
Short Answer: Luceros answer is correct: it is optional
I have to maintain sql and adapt it between sql-server and Oracle. Here are some rules:
Write Scripts manually, don't use generated code.
Always use INSERT INTO.
Always DELETE -- without FROM.
Do not use " - quoted identifier.
Remove all [ ] and dbo. (Schema names)
Attention when you see DELETE ... FROM ...
Attention when you see UPDATE ... FROM ...
ORACLE Select statements need a from clause you can use from DUAL
OK you can script your objects and edit them in a standard way
USE [Current_DB] -- you don't want a reference to your test database go into production script
SET ANSI_NULLS ON -- decide once which settings to use -- don't switch on and off
SET QUOTED_IDENTIFIER ON -- quoted identifiers are case-sensitive.
INSERT INTO is required by Oracle.
That is my personal style don't use optional keyword, learn the defaults
You have to quote an identifier, if you use one of ORACLES reserved keywords as column name, we entered that pitfall and in the long run it would have been better to rename the column on the sql-Server side.
Oracle doesn't use these.
Oracle doesn't support this syntax.
Oracle doesn't support this syntax.
From the Microsoft SQL Server documentation, FROM is optional.
from is optional in delete from in those three DBMSes but it is mandatory according to the SQL standard. I would always use delete from to ease the migration of SQL code from one DBMS to another.
In SQL Server, FROM of DELETE FROM is optional and DELETE without FROM is not SQL standard while DELETE FROM is SQL standard.
I 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
In addition, I also experimented INSERT INTO and INSERT without INTO 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

How to drop all triggers in a Firebird 1.5 database

For debug purposes I need to send 1 table of an existing Firebird 1.5 database to someone.
In stead of sending the whole db , I want to send just the db with just this table - no triggers, no constraints. I can't copy the data to another db because it's just that that we want to check - why this one table is given troubles.
I am just wondering if there is a way to drop all triggers , all constraints and all but one table (using some clever trick with the system tables or so ) ?
Using GUI tool (I personally prefer IBExpert) execute following command:
select 'DROP TRIGGER ' || rdb$trigger_name || ';' from rdb$triggers
where (rdb$system_flag = 0 or rdb$system_flag is null)
Copy result into clipboard then paste and execute within script executive
window.
If your database backup can switch to Firebird 2.1 there is some switch in gbak and isql.
Some Firebird command-line tools have
been supplied with new switches to
suppress the automatic firing of
database triggers:
gbak -nodbtriggers
isql -nodbtriggers
nbackup -T
These switches can only be used by the
database owner and SYSDBA.
You can drop all triggers by directly deleting them from the system table, like so:
delete from rdb$triggers
where (rdb$system_flag = 0 or rdb$system_flag is null);
Note that the normal way of using drop trigger is certainly preferable, but it can be done.
You can also drop constraints by executing DDL statements, but to enumerate constraints and drop them in a SQL script you would need the execute block functionality that Firebird 1.5 doesn't have.
There are similar statements to delete other database objects, but actually running these successfully may be much more difficult because of dependencies between objects. You can't drop any object as long as another object depends on it. This can become really tricky due to circular references, where two (or even more) objects depend on one another, forming a cycle, so there isn't a single one that may be dropped first.
The way around this is to break one of the dependencies. A procedure for example that has dependencies to other objects can be altered to have an empty body, after which it does no longer depend on those other objects, so they may be dropped then. Dropping foreign keys is another way of eliminating dependencies between tables.
I don't know of any tool implementing such a partial delete of database objects, your use case is IMO far from common. You could however have a look at the FlameRobin source code which has a certain amount of dependency detection in the code that is used to create DDL scripts or modification statements for database objects. Armed with that information you could write your own tool to do it.
If it's a one time thing it may be enough to do this manually, though. Use any Firebird management tool of your choice for that.

SqlBulkInsert - How to set Fire Triggers, Check Constraints?

I'm performing a bulk insert with an ADO.NET 2.0 SqlBulkCopy object from a C# method into a MS SQL 2005 database, using a database user with limited permissions. When I try to run the operation, I get the error message:
Bulk copy failed. User does not have
ALTER TABLE permission on table
'theTable'. ALTER
TABLE permission is required on the
target table of a bulk copy operation
if the table has triggers or check
constraints, but 'FIRE_TRIGGERS' or
'CHECK_CONSTRAINTS' bulk hints are not
specified as options to the bulk copy
command.
I read some documentation and created the bulk copy object with the constructor that lets me specify such things:
SqlBulkCopy bc = new SqlBulkCopy(
System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"],
SqlBulkCopyOptions.FireTriggers & SqlBulkCopyOptions.CheckConstraints);
But this doesn't change anything - I get the same error message as before. I tried fiddling with some of the other SqlBulkCopyOptions values but no luck. I really thought this would fix the problem, am I missing something?
I tested the procedure after granting ALTER on the table to my user, and the operation succeeded. However this is not an option for my situation.
Solved it! Looks like I need a refresher on flags enums. I was bitwise ANDing the enum values when I should have been ORing them.
SqlBulkCopyOptions.FireTriggers & SqlBulkCopyOptions.CheckConstraints
evaluates to zero (which is equivalent to SqlBulkCopyOptions.Default.)
SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.CheckConstraints
Worked correctly and allowed the bulk insert to complete.
Possibilities only, I'm sorry
SQL documentation for BULK INSERT specifies 3 cases where ALTER TABLE is needed. You listed 2 of them. Is the KeepIdentity option being set, even if not needed?
Another option is that the trigger on the table is disabled already, confusing the issue. Use ALTER TABLE dbo.SomeTable ENABLE TRIGGER ALL to ensure enabled.