I am trying to write "re-usable" SQL script with ADD COLUMN clause for Informix server. Normally, I can only run it once, because then the column already exists and it cannot be added again. And I cannot just add DROP column as prior statement, because it would fail during the first execution. I need something like DROP COLUMN IF EXISTS, but unlike dropping other SQL entities, it is not available for columns.
I can ask system tables whether the column is present in then DB via:
SELECT c.colname
FROM "informix".systables AS t
JOIN "informix".syscolumns AS c ON t.tabid = c.tabid
WHERE c.colname = 'col_name' and t.tabname = 'tab_name'
plus I found some proposed solutions for workarounds, but I guess they are for different SQL servers, since I cannot figure out how to put it together into valid SQL script acceptable for my Informix.
Any clues? Or is it mission impossible?
As things stand, Informix's ALTER TABLE statement has no DROP COLUMN IF EXISTS clause, nor an ADD COLUMN IF NOT EXISTS clause (nor a separate DROP COLUMN statement — though it does have a separate RENAME COLUMN statement).
You would have to wrap the logic to detect whether the column exists in a shell script and decide based on that whether to add the column. Or, alternatively, you'd have to submit the ADD operation and ignore the 'column already exists' error.
Related
How do I drop a few tables (e.g. 1 - 3) using the output of a SELECT statement for the table names? This is probably standard SQL, but specifically I'm using Apache Impala SQL accessed via Apache Zeppelin.
So I have a table called tables_to_drop with a single column called "table_name". This will have one to a few entries in it, each with the name of another temporary table that was generated as the result of other processes. As part of my cleanup I need to drop these temporary tables whose names are listed in the "tables_to_drop" table.
Conceptually I was thinking of an SQL command like:
DROP TABLE (SELECT table_name FROM tables_to_drop);
or:
WITH subquery1 AS (SELECT table_name FROM tables_to_drop) DROP TABLE * FROM subquery1;
Neither of these work (syntax errors). Any ideas please?
even in standard sql this is not possible to do it the way you showed.
in standard sql usually you can use dynamic sql which impala doesn't support.
however you can write an impala script and run it in impala shell but it's going to be complicated for such task, I would prepare the drop statement using select and run it manually if this is one-time thing:
select concat('DROP TABLE IF EXISTS ',table_name) dropstatements
from tables_to_drop
We have a table on the SQL Server 2008 which gets populated by various stored procedures. The problem is that the authors of these stored procedures used some poor choice in code and populated this table using the following syntax:
INSERT INTO persistant_table
SELECT *
FROM #temp_table_with_data
Basically they would create a #temp_table_with_data in the script and the columns would be in the same order and with the same name as they are in the persistant_table.
Now I need to add another column to this persistant_table, but if I do that, I will break all the stored procedures.
Is there a way for me to add a column to this table without breaking all the stored procedures? (In the long run, we will change the stored procedures).
Thank you
No I think.select * will pick all columns and column number should match.
I don't think it's big effort to change the line to have particular columns only or select statement to have default value for column or null and then * to store into columns sequentially. But at least 1 line to be changed
The "ALTER TABLE" is a SQL statement that allows you to make datatype changes to a database table (i.e. change datatype as well as Size columns from an existing table).
ALTER TABLE TableName ALTER COLUMN ColumnName NVARCHAR(200)
You cannot do it without affecting old scripts. This is why 'SELECT *' is not good practice. You'd better create new scripts with explicit column names like
SELECT column1, column2 ....
I have a table which has 50+ columns but only few columns are getting used. that means when any stored procedure uses that table it only refers 4-5 columns in select/where statements . rest of columns are not getting used . i just want to list down those columns that are actually getting used. one way is finding out the dependencies of a table and then go through every SP and find out which columns are getting used . but in that case i have around 30+ Sp. is there any efficient way to do it.
To use multiple columns in a procedure, you can use a code like below
create procedure sp_sample
#column_names varchar(200)
as
if #column_names='' or #column_nams is null
set #column_names='*'
exec ('select '+#column_name +' from table')
Here are some examples :
exec sp_sample #columnname='id,name'
or
exec sp_sample #columnname='id,name,telphone'
Try this:
select name from syscomments c
join sysobjects o on c.id = o.id
where TEXT like '%table_name%' and TEXT like '%column_name%'
In table_name give you table name, in column_name give the column for which you want to chck the procedure dependencies.You will get the stored procedure names as output
If you import your database as a database project using the SQL Server Data Tools, you will be able to find all references to a table or column using the "Find All References" context command. What makes this particularly useful is the accuracy: it will even find instances of SELECT * that don't mention the column explicitly, but implicitly refer to it anyway. It will also not be confused by tables or columns with similar names (finding particular instances of ID is otherwise rather problematic).
If all you want to know if a column is referenced at all, you can simply delete it and see if any "unresolved reference" errors appear in the error list -- if yes, then the column is used somewhere.
How can I add a column in an SQLite table if and only if the same column does not exist in the table?
Using ALTER TABLE I am able to create a new column but want to know how to check whether that column already exists in the table or not?
SQLite returns an error like "no such column: foo" if the table doesn't contain the column:
select foo from yourTable limit 1
Also you can get the create-table statement:
select sql from sqlite_master where tbl_name = 'YourTableName'
and then parse the result, looking for the column-name. I don't know of an elegant way to query the list of columns for a specified table, though one may exist.
Also if you attempt to do this:
alter table YourTable add column foo {column-def whatever it is}
you get an error from SQLite if the column already exists. You could trap that error too.
Finally you could do this:
select sql from sqlite_master
where tbl_name = 'YOURTABLE' and sql like '%"foo" CHAR%'; -- or whatever type
and if the specified table contains the column which is surrounded by double-quotes in the query, and with the type you have specified, you will get a result, otherwise an empty set. Specifying the datatype ensures that your LIKE substring match occurs on a column-name.
There's no way (that I know of) to do it all in a single SQLite query. You must use application code to manage the If/Elseness.
Check if table exists or not:
select count(*) from sqlite_master where type = 'table' and name = MyTable';
Check if column exists in table or now
pragma table_info(thumbnail);
However, a better approach may be explicit database schema updates based on schema versions your application maintains (e.g. specific alter table statement to go from schema version 1 to 2):
pragma user_version;
It seems like that it is impossible to do checking if the column not exists and addindg the new column in one command, because Sqlite don't support "IF NOT EXISTS" for column. "IF NOT EXISTS" works only on table.
Here is what I will do:
rev = ExecuteStatement("SELECT columnNamexx FROM tableNamexx limit 1;");
if(rev != SQLITE_OK){ // add col to table
ExecuteStatement("ALTER TABLE tableNamexx ADD COLUMN columnNamexx INTEGER DEFAULT 0;");
}
You can view the table columns by using '.schema tableName'
I have a table in informix (Version 11.50.UC4) called NextRecordID with just one column called id and it will have one row. What I want to do is copy this value into another table. But don't want my query to fail if this table does not exist. Something like
if table NextRecordID exists
then insert into sometable values ('NextRecordID', (select id from NextRecordID))
else insert into sometable values ('NextRecordID', 1)
I ended up using the below SQL query. Its not ANSI SQL but works the informix server I am using.
insert into sometable values ('NextRecordID',
select case (select 1 from systables where tabname='nextrecordid')
when 1 then (select nextid from nextrecordid)
else (select 1 from systables where tabname='systables') end
from systables where tabname='systables');
What is happening here is within insert query I get the value to be inserted by using select query. Now that select query is interesting. It uses case statement of Informix. I have written a select query to check if the table nextrecordid exists in systables and return 1 if it exists. If this query returns 1, I query the table nextrecordid for the value or else I wrote a query to return the default value 1. This work for me.
You should be able to do this by checking the systables table.
Thank you for including server version information - it makes answering your question easier.
You've not indicated which language(s) you are using.
Normally, though, you design a program to expect a certain schema (certain tables to be present), and then fail - preferably under control - if those tables are not present. Also, it is not clear whether you would get into problems because of repeated execution of the second INSERT statement. Nor is it clear when the NextRecordID table is updated - presumably, once the value has been used, it must be updated.
You should look at SERIAL (BIGSERIAL) and see whether that is appropriate for you.
You should also look at whether a SEQUENCE would be appropriate to use here - it certainly looks rather like it might be applicable.
As Adam Hughes points out, if you want to check whether the NextRecordID table is present in the database, you would look in the systables table. Be aware, though, that your search will need to be against an all lower-case name (nextrecordid).
Also, MODE ANSI databases complicate life - you have to worry about the table's owner (because there could be multiple tables called nextrecordid in a MODE ANSI database). Most likely, you don't have to worry about that - any more than you are likely to have to worry about delimited identifiers for table "someone"."NextRecordID" (which is a different table from someone.NextRecordID).