creating a table only if it's not existing with ANSI sql - 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

Related

Finding any reference to a given string in Oracle DB

I want to delete a table from the database, which I know is not being used anywhere in our Java code-base. I was able to also delete it from our DB, but I'm not sure that this may not still pose some kind of problem. Maybe it can still be referenced from a Stored Procedure, or something of the like?
Or does the database actually guarantee that under any circumstance this will not be the case when deleting a table? In case it may be a problem, what would be the best way to search for this specific string in the db such as to find its possible usages?
Unfortunately I don't have dba access to this db.
Thanks
no such guarantee
but you can run this to find any reference to the table in a stored procedure, package or function
select * from dba_source where lower(text) like '%<tablename>%'
I think there are 2 reference of table you need to care about.
Dependencies (in table browser, sql navigator/toad has, not sure about others)
Dynamic sql call that table in procedure/function/package. Refer here
But those're not all, because some dynamic sql may use string concatenate
execute immediate 'select max(name) from customer_' || provinceCode into testName;

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

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

How can I insert column comments through a Standard SQL script?

I want a script that inserts table comments and column comments. Said script must be unique and run satisfactorily both on Oracle and MySQL. Furthermore, I prefer it to be written in Standard SQL.
This is how I do it now. But it does not work on MySQL.
comment on table F_Transaction
is 'Fact table for system transactions';
comment on column F_Transaction.Transaction_Date
is 'Date in which the transaction took place';
What SQL construction should I use to achieve my purpose?
The standards do not seem to define any way to define table or column comments (looks like they don't even mention them). So, the syntax for comments on tables/columns can vary from one DBMS to another.
It seems that a number of DBMS agree with Oracle's COMMENT ON syntax (see Oracle create table with column comments).
With MySQL it's necessary to specify the comments along with the table/column definition (in CREATE TABLE or ALTER TABLE sentences). See this related question: Alter MYSQL Table To Add Comments on Columns.

Oracle create table with column comments

Is there a column comment syntax that allows me to specify a column comment directly where I declare the column in the create table statement (i.e. inline)? The 11g spec does not mention anything, on another page something is mentioned but I could not get it to work. There is a way to specify comments after creating the table, but I think it is annoying that the comment is separated from the field definition. I am looking for something like this (which does not work):
create table whatever (
field number(15,0) primary key comment 'primary key generated from sequence pkseq',
...
)
I'm afraid the "annoying" COMMENT ON syntax is the only way of doing this. SQL Server, PostgreSQL and DB2 use the same syntax (even though, as far as I know, there is no ANSI standard syntax for adding comments to database objects).
MySQL supports the way you would like it to work. I agree it would be a nicer mechanism, but in my experience so few people use comments at all that I doubt Oracle will ever change it.
I'm afraid it can only be done after table creation, using the comment on column ... is '' syntax.
A workaround to this annoying syntax is also to view and edit the tables in Oracles SQLExplorer. It contains a wizard that allows you to edit the comments right next to the columns. It even allows easy creation of alter table scripts.
My procedure when editing tables is to enter the changes in the wizard without actually executing them, then go to its DDL tab and retrieve the SQL from there (as update, not full create script) and press cancel on the wizard. Then I put the created SQL into the SQL script I am writing. Only when I am finished with the script I execute everything; I do never make any changes with the wizard itself.
Test on sqlplus (or similar), but the syntax is as follows:
-- assuming you have privileges
COMMENT ON COLUMN SCHEMA1.TABLE1.COL1
IS 'My comment'
-- then you can double check like this
SELECT * FROM all_col_comments WHERE
(OWNER, TABLE_NAME, COLUMN_NAME)
IN (('SCHEMA1','TABLE1','COL1'));
Note that the comment will now show in SQLDeveloper (or Toad or whatever env you have) until you reopen said table's properties.
Similar syntax can be used to annotate tables, indexes and materialized views. [source: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_4009.htm]
I understand similar syntax exists for MySQL and others, but it is not proper ANSI. It's very useful, though.

Best way to handle LOBs in Oracle distributed databases

If you create an Oracle dblink you cannot directly access LOB columns in the target tables.
For instance, you create a dblink with:
create database link TEST_LINK
connect to TARGETUSER IDENTIFIED BY password using 'DATABASESID';
After this you can do stuff like:
select column_a, column_b
from data_user.sample_table#TEST_LINK
Except if the column is a LOB, then you get the error:
ORA-22992: cannot use LOB locators selected from remote tables
This is a documented restriction.
The same page suggests you fetch the values into a local table, but that is... kind of messy:
CREATE TABLE tmp_hello
AS SELECT column_a
from data_user.sample_table#TEST_LINK
Any other ideas?
The best solution by using a query as below, where column_b is a BLOB:
SELECT (select column_b from sample_table#TEST_LINK) AS column_b FROM DUAL
Yeah, it is messy, I can't think of a way to avoid it though.
You could hide some of the messiness from the client by putting the temporary table creation in a stored procedure (and using "execute immediate" to create they table)
One thing you will need to watch out for is left over temporary tables (should something fail half way through a session, before you have had time to clean it up) - you could schedule an oracle job to periodically run and remove any left over tables.
For query data, the solution of user2015502 is the smartest. If you want to insert or update LOB's AT the remote database (insert into xxx#yyy ...) you can easily use dynamic SQL for that. See my solution here:
You could use materalized views to handle all the "cache" management. It´s not perfect but works in most cases :)
Do you have a specific scenario in mind?
For example, if the LOB holds files, and you are on a company intranet, perhaps you can write a stored procedure to extract the files to a known directory on the network and access them from there.
In this specific case can the only way the two systems can communicate is using the dblink.
Also, the table solution is not that terrible, it's just messy to have to "cache" the data on my side of the dblink.