A not-existing column should not break the sql query within select - sql

In my case there are different database versions (SQL Server). For example my table orders does have the column htmltext in version A, but in version B the column htmltext is missing.
Select [order_id], [order_date], [htmltext] from orders
I've got a huge (really huge statement), which is required to access to the column htmltext, if exists.
I know, I could do a if exists condition with two begin + end areas. But this would be very ugly, because my huge query would be twice in my whole SQL script (which contains a lot of huge statements).
Is there any possibility to select the column - but if the column not exists, it will be still ignored (or set to "null") instead of throwing an error (similar to the isnull() function)?
Thank you!

Create a View in both the versions..
In the version where the column htmltext exists then create it as
Create view vw_Table1
AS
select * from <your Table>
In the version where the htmlText does not exist then create it as
Create view vw_Table1
AS
select *,NULL as htmlText from <your Table>
Now, in your application code, you can safely use this view instead of the table itself and it behaves exactly as you requested.

First thing why a column would be missing? definitely its been deleted somewhere. if so, then the delete process must have updated/fixed the dependencies.
Instead fixing it after breaking, its better to do smart move by adopting some protocols before breaking anything.
IF Exists is a workaround that can help to keep queries running but its an overhead considering your huge database and queries

The "best" way to approach this is to check if the column exists in your database or not, and build your SQL query dynamically based on that information. I doubt if there is a more proper way to do this.
Checking if a column exists:
SELECT *
FROM sys.columns
WHERE Name = N'columnName'
AND Object_ID = Object_ID(N'tableName');
For more information: Dynamic SQL Statements in SQL Server

Related

If not exist clause SQL statement

so I found this sql query in a project I am succeeding. This is the first time I encountering this clause/statement. I understand that this is to look if the table exist before creating one and that Object_ID is the table name that is to be created.
My questions are:
Does sysobject mean the database?
What is the Object property?
I know that it is not the columns inside the table to be created.
The columns are : dtb_color_id and description.
can someone explain this to me. please?
IF NOT EXISTS(SELECT * FROM SYSOBJECTS WHERE ID = OBJECT_ID('DTB_COLOR') AND OBJECTPROPERTY(ID,'ISUserTable') = 1)
BEGIN
.......some query I understand
END
sysobjects, OBJECTPROPERTY and OBJECT_ID are used in Microsoft SQL Server. They are part of the SQL Server DMVs and system functions/procedures used to query and manipulate the metadata.
sys.sysobjects is simply the list of all objects (tables, views, SPs, functions, etc) on the server in the active database. Please note, that sys.sysobjects is deprecated and is only available for backward compatibility. Use sys.objects instead
https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/system-dynamic-management-views?view=sql-server-ver16
It has (as far as I know) no meaning in MySQL, unless somebody specifically created them.
You can also use INFORMATION_SCHEMA which is available in MySQL too (however slightly different in different RDBMS).
MSSQL INFORMATION_SCHEMA: https://learn.microsoft.com/en-us/sql/relational-databases/system-information-schema-views/system-information-schema-views-transact-sql?view=sql-server-ver16
MySQL INFORMATION_SCHEMA: https://dev.mysql.com/doc/refman/8.0/en/information-schema.html
SQL Server has no CREATE TABLE IF NOT EXISTS construct, a variation of the mentioned condition is commonly used to imitate that.
This is a way in SQL Server to check if a table exists in the active database and to perform actions according to the result, like creating the table.
OBJECTPROPERTY simply checks (in this case) if the table is a user created one.
https://learn.microsoft.com/en-us/sql/t-sql/functions/objectproperty-transact-sql?view=sql-server-ver16
I would remove the OBJECTPROPERTY condition in case the part you understand is a CREATE TABLE statement. You don't want to create a table which has a similar name to any system table/view, also you don't want to execute the CREATE TABLE if there is a VIEW with the same name (table creation will fail)
Yes sysobject means database.
The OBJECTPROPERTY() function returns information about schema-
scoped objects in the current database. Use this to check if an
object is a table, view, stored procedure, etc. You can also use
it to check if a table has a primary key, foreign key, foreign
key reference, etc.
For more details : https://learn.microsoft.com/en-us/sql/t-sql/functions/objectpropertyex-transact-sql?view=sql-server-ver16
In this scenario it is used to check whether it is user table or
not. The result of the ISUserTable property is 1 when it is user
table otherwise returns 0.
Here the following steps are followed:
First, it executes the select statement inside the IF Exists
If the select statement returns a value that condition is TRUE for IF Exists
It starts the code inside a begin statement
DTB_COLOR - May be a stored procedure

Retrieve Script used in "Create Table As" Statement

We have a table in our Oracle Database that was created from an actual script.
Ex:
Create Table AS (Select * from table).
I was hoping to recover the original script the table was created from as the data is quite old in the table, but needs this created table needs to be refreshed. This table is created with data from another live table in our database, so if there is a way to refresh this without the original query - I'm open ears. Any solutions are welcomed!
Thanks!
I suppose you could also do a column by column comparison of this table against all others to see which one (if any) matches it. Of course, this would only be a guess.
It would require that object to actually be a materialized view instead of a table. Otherwise you are probably left off with exploring logs. Beyond that I doubt there is any way to recover the original select statement used to create that table.

creating a table only if it's not existing with ANSI sql

I am trying to dynamically create a SQL table only if it's not already existing. I have seen many solutions on the internet but they usually rely on a specific database, while I'm trying to find the most generic solution.
I was thinking of always running the CREATE command and then assuming that if it fails then the table exist and I can start inserting data into it. I can't see any flaw in this reasoning (not counting performance issues), but I might be wrong.
Is this an acceptable method?
Can you suggest other methods which are database independent, or that use ANSI SQL that all RDBMS would accept?
if there is a table - say - EMP, does that really imply that it is the same EMP that you are expecting?
Either query the appropriate data dictionary for the table structure, or fill your code with a ton of error checking and conditional logic...
INFORMATION_SCHEMA is part of the ANSI SQL Standard, so you should be able to:
IF NOT EXISTS(SELECT NULL FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'YourTable')
CREATE TABLE...
what about: create table if not exists

if column not exists alter table

I use the SQL script that was generated (sql 2k5), to add a column to a table.
I need to add a "check if exists" because my clients sometimes run the script twice. (i have no control over this part, and this is happening over and over again)
I found a way joining the sysobjects and syscolumns, it works.
My problem is that I have to add a column to an other table, where the column is not at the end of the table.
For this one, SQL is generating that long code ... create new temp table with the new column, filling up from old table, dropping the old table, and finally renaming the temp table.
The issue here is that the script for this one has lots of GO -s in there along with transactions ...
What can i do?
1.) remove all the GO - s? (don't like the idea)
2.) adding my IF between every GO pair? (don't like the idea)
3.) is there an other way that makes sense, and it would not be too hard to implement
I cannot think of anything really, I could check for release version, or anything, not just my sysobjects and syscolumns join, but the issue will be the same.
because of the GO-s, my If will be "forgotten" when it gets to the END of the BEGIN ...
I'm not sure I follow the entirety of your question, but you would check for the existence of a column like this:
if not exists (select * from information_schema.columns
where table_name = '[the tables name]'
and column_name = '[column name')
begin
--alter table here
end
Why worry about the ordinal position of the column? New columns get a new colid and are appended to the "end", this shouldn't cause any problems.
If you make frequent updates by shipping these kinds of scripts, I would create a version table and just query this at the beginning of the script.
How are they running the scripts (since you are using a tool which supports the GO batch separator) - SQL CMD?
I would consider putting it all in a string and using EXEC. Several DDL commands have to be the first command in a batch. Also, you can sometimes run into parsing issues:
ALTER TABLE Executing regardless of Condition Evaluational Results
Also, you may want to look at SQLCMD's control features http://www.simple-talk.com/sql/sql-tools/the-sqlcmd-workbench/

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)