TSQL substitution of key words and code blocks - sql

I have blocks of TSQL that I want to create a MACRO for and then reuse in my SQL file. I want this to be a 'compile' time thing only.
Eg:
?set? COMMON = "Field1 int, Field2 char(1),";
?set? MAKEONE = "create table";
MAKEONE XXX (
COMMON
Field3 int
);
Please dont ask why I would want to ... :)
... it is for SQL Server.
Ok, what about conditional execution of SQL:
?set? ISYES = true;
?if? ISYES
create table AAA (...)
?else?
create table BBB (...)

What you are asking makes little sense in SQL terms
Based on your examples:
A CREATE TABLE is exactly that: a CREATE TABLE. Why Macro it? You aren't going to substitute "CREATE PROCEDURE".
Having "common" fields would indicate poor design
You also have to consider:
constraints, keys and indexes
permissions of using dynamic SQL
the cost of developing a "framework" to do what SQL already does
permissions of your objects
Now, what is the business problem you are trying to solve?
Instead of asking about your chosen solution...
Edit: question updated as I typed above:
IF (a condition)
EXEC ('CREATE TABLE ...')
ELSE IF (a condition)
EXEC ('CREATE TABLE ...')
...
Note that much of DDL in SQL must be in it's own batch or the first statement in a batch. Hence use of dynamic SQL again

Related

How to get CREATE TABLE Statement from existing table in db2?

I am using DB2 and Oracle SQL Developer.
How to get the CREATE TABLE Statements from the existing tables?
There are too many tables and it will be a very lengthy process to do manually.
There is a special db2look utility for DDL extraction in Db2. You may refer to its options and their meaning at this link.
If you want SQL access to its capabilities, you may use the SYSPROC.DB2LK_GENERATE_DDL stored procedure supporting most of the utility's options. The routine has an output parameter getting "invocation number" int value after its call.
In case of a single table:
CALL SYSPROC.DB2LK_GENERATE_DDL ('-e -noview -t MY_SCHEMA.MY_TABLE', ?);
SELECT SQL_STMT
FROM SYSTOOLS.DB2LOOK_INFO_V
WHERE OP_TOKEN = <value_of_output_parameter_from_call_above>
ORDER BY OP_SEQUENCE;
In SQLDeveloper if you can see the table there's the initial Create Table Statement in the SQL Tab
You should do that for each table, this is a way to do it but I'm not sure it's fast enough for you.

SQL SERVER table alias in stored proc

Is there a way to give an alias to a table which will then be referenced within a store procedure.
Declare #target= (sometalbewithveryverylonganduglyname)
Declare #source= (anothertablewithaveryuglyverylongverybadname)
Select * from #target
Insert into #target select from #source
delete from #source
Reason being, the table source and target could change (if the tablename is changed then we just change in one location), and for better readability.
In T-SQL you can't do:
Select * from #target
unless #target is defined as a table-variable, which requires you to set up the table as a user-defined type first. If you're attempting to assign the name of a physical table to the variable and access it this way you'd need to execute the statement using dynamic SQL.
exec ('Select * from #target')
If you just want to alias the table you could write your query like this:
Select * from sometalbewithveryverylonganduglyname AS t
From your question, sounds like the table name can change so you're going to need to use dynamic SQL in the end.
You can't do what you describe unless you resort to dynamic SQL as Yuck suggested, but doing that for the sake of not writing a long table name is not a valid justification. SSMS already includes intellisense and for SQL Server 2005 and below, you can use one of many of the free tools out there. That should reduce the amount of typing that you need to do as well as misspelling mistakes.
Besides, you can always do select t.column1 from really_long_and_ugly_name t ...
option 1) In that case you don't want to use a stored procedure, use some ORM library, it will allow you to switch between different table names with the same structure very easy
option 2) use views, that's what they are for, to hide underlying tables and allow those types of changes

automate schema creation in PostgreSQL (maybe plpgsql?)

I have a big database (in PostgreSQL 8.4) which I try to analyse in smaller parts. To do that, I copy parts of the content of the big database to other schemas (I know it is somehow against the philosophy of databases to copy data, but without that step the analysis is too slow).
There are quite a few SQL-commands that I need to perform, to get a new schema with all necessary tables inside it. However, the difference between the creation of one schema to the creation of another schema is very small (in principle its just the name of the schema and a different value in a "WHERE"-clause).
My question is the following:
Is it possible to write a function that takes a certain value as a parameter and uses this parameter in the where clause (and as the name of the schema?)
If it is possible, which program-language would you suggest (maybe plpgsql), and what would such a script look like (just as a skeleton)?
Thank you in advance!
Not sure I'm making perfect sense of your question, but it sounds like should be using the temporary schema:
create temporary table foo as select * from bar where ...
On occasion it's also useful to use the same name:
create temporary table foo as select * from foo where ...
Else yes, dynamic SQL works:
create function do_stuff(_table regclass) returns void as $$
begin
execute 'select 1 from ' || _table;
end; $$ language plpgsql strict;
select do_stuff('schemaname.tablename');
http://www.postgresql.org/docs/9.0/interactive/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

MySQL Stored Procedure dynamic change name of table

I wanna change dynamicaly name of table in sql query. For example I have next stored procedure:
CREATE PROCEDURE NewProc(IN tableName varchar(64),IN message text)
BEGIN
INSERT INTO tableName VALUES (message);
END;
I need to change tableName in runtime, Can I to do it or not?
Thanks.
You must use dynamic SQL to prepare and execute an SQL string, to achieve what you describe.
Dynamic table names (or column names, or SQL keywords, etc.) must be interpolated into the SQL string before prepare. You can't use query parameters for these dynamic elements.
Be careful to avoid SQL injection vulnerabilities when you interpolate the table name into your SQL query. For example, you should check that the table name exists by looking it up in the information schema.
I agree with the comment from #OMG Ponies -- it's a code smell that you have multiple tables with identical structure such that you want to do the exact same insert to the exact same column. Code smells aren't a guarantee that you've got a bad design, but it's worth considering.

Re-runnable SQL Server Scripts

What are the best practices for ensuring that your SQL can be run repeatedly without receiving errors on subsequent runs?
e.g.
checking that tables don't already exist before creating them
checking that columns don't already exist before creating or renaming
transactions with rollback on error
If you drop tables that exist before creating them anew, drop their dependencies first too, and don't forget to recreate them after
Using CREATE OR ALTER PROCEDURE instead of CREATE PROCEDURE or ALTER PROCEDURE if your flavor of SQL supports it
Maintain an internal versioning scheme, so the same SQL just doesn't get run twice in the first place. This way you always know where you're at by looking at the version number.
Export the existing data to INSERT statements and completely recreate the entire DB from scratch.
dropping tables before creating them (not the safest thing ever, but will work in a pinch if you know what you're doing)
edit:
I was looking for something like this:
IF EXISTS ( SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[foo]')
AND OBJECTPROPERTY(object_id, N'IsUserTable') = 1 )
DROP TABLE foo
Do others use statements like this or something better?
edit:
I like Jhonny's suggestion:
IF OBJECT_ID('table_name') IS NOT NULL DROP TABLE table_name
I do this for adding columns:
IF NOT EXISTS ( SELECT *
FROM SYSCOLUMNS sc
WHERE EXISTS ( SELECT id
FROM [dbo].[sysobjects]
WHERE NAME LIKE 'TableName'
AND sc.id = id )
AND sc.name = 'ColumnName' )
ALTER TABLE [dbo].[TableName] ADD [ColumnName]
To make things easier I configure management studio to script objects as rerunnable
Tools
Options
SQL Server Object Explorer
Scripting
Object scripting options
Include IF Not Exists Clause True
I think the most important practice in ensuring that your scripts are re-runnable is to....run them against a test database multiple times after any changes to the script. The errors you encounter should shape your practices.
EDIT
In response to your edit on syntax, in general I think it is best to avoid the system tables in favor of the system views e.g.
if exists(Select 1 from information_schema.tables where table_name = 'sometable')
drop sometable
go
if exists(Select 1 from information_schema.routines where
specific_name = 'someproc')
drop someproc
To add to your list:
If you drop tables that exist before creating them anew, drop their dependencies first too, and don't forget to recreate them after
Using CREATE OR ALTER PROCEDURE instead of CREATE PROCEDURE or ALTER PROCEDURE if your flavor of SQL supports it
But ultimately, I would go with one of the following:
Maintain an internal versioning scheme, so the same SQL just doesn't get run twice in the first place. This way you always know where you're at by looking at the version number.
Export the existing data to INSERT statements and completely recreate the entire DB from scratch.
I recently found a check-in for existence that i didn't know existed and i liked it because it's shorter
IF OBJECT_ID('table_name') IS NOT NULL DROP TABLE table_name
before, i used to use
IF EXISTS (SELECT * FROM information_schema.tables WHERE table_name = 'table_name')
DROP TABLE table_name
Which i found useful because it's a little more portable (MySql, Postgres, etc), taking into account the differences, of course
For maintaining schemas, look at a migration tool. I think LiquiBase would work for SQL Server.
You'll also need to check for foreign keys on any tables that you may be dropping/recreating. Also, consider any data changes that you might make - delete rows before trying to insert a second time, etc.
You also might want to put in code to check for data before deleting tables as a safeguard so that you don't drop tables that are already being used.
For a SQL batch statement, you can issue
This is just a FYI, I just ran it 10 times
IF EXISTS ( SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[foo]')
AND OBJECTPROPERTY(object_id, N'IsUserTable') = 1 )
DROP TABLE foo
GO 10 -- run the batch 10 times
This is just a FYI, I just ran it 10 times
Beginning execution loop Batch
execution completed 10 times.
The "IF OBJECT_ID('table_name', 'U') IS NOT NULL" syntax is good, it can also be used for procedures:
IF OBJECT_ID('procname', 'P') IS NOT NULL
...
... and triggers, views, etc... Probably good practice to specify type (U for table, P for prog, etc.. dont remember the exact letters for all types) in case your naming strandards allow procedures and tables to have similar names...
Furthermore, a good idea might be to create your own procedures that changes tables, with error handling proper to your environment. For example:
prcTableDrop, Proc for droping a
table
prcTableColumnAdd, Proc for adding a column to a table
prcTableColumnRename, you get the idea
prcTableIndexCreate
Such procs makes creating repeatable (in same or other db) change scripts much easier.
/B
I've describe a few checks in my post DDL 'IF not Exists" conditions to make SQL scripts re-runnable
Just adding this for future searchers (including myself), such scripts are called idempotent (the noun being idempotency)