1

I have a procedure that at some point does a copy of a row from tableA + some fields to tableB like this:

INSERT INTO tableB
SELECT a.*, 'field1', 'field2'
FROM tableA a
WHERE a.id = myId

The problem came when I had to add a new column to tableA. If I add the column to tableA it's added as the last column, making this procedure invalid cause number of columns doesn't match. For this script to make sense I should add the new column from tableA to tableB. I could write all the columns by hand, but there are a lot of columns and I'm looking for something more maintainable

Is there a way to add the new column to tableB at a specific position? If it's not posible, is there a way to select every column from tableA except the new one (So I can select it as last one for tableB)? And if not, how can I automatize the column order selection/insertion?

Thanks

Mr. E
  • 2,070
  • 11
  • 23
  • Please add the table scripts with this questions. – Md. Shamim Al Mamun Jan 22 '16 at 16:24
  • 2
    There is no way in SQL that I know of, which would allow you to select every column but those specified. Consider using event triggers to automatically create a column in `tableB`. If you want the maintenance work to be done by hand, generate list of `tableA` columns once and put them into your procedure handling adding new column to `tableB` when some changes are made on a structure of `tableA` – Kamil Gosciminski Jan 22 '16 at 16:25
  • @Md.ShamimAlMamun I'm sorry, it's code from work, I can't add table definitions. Is some specific part about the table scripts useful? – Mr. E Jan 22 '16 at 16:29
  • 2
    Typing the columns out is maintainable. You only have to do it once, right? – Dan Bracuk Jan 22 '16 at 17:01

1 Answers1

4

This is one of the reasons select * is often considered a bad idea in anything except ad hoc queries (and sometimes subqueries, and pivots). If the table structure changes you're a bit stuck.

You cannot select all but some columns. You also can't add a new column to a table in a specific position. You could recreate the table but that invalidates anything that refers to it, and may be too slow or use too much storage. You may be able to use the DBMS_REDEFINITION package to make that less painful and visible, if your table is suitable. But you probably don't want to do that every time the structure changes.

Another option which I wouldn't recommend is making your insert a dynamic SQL statement with the column names generated at runtime from user_tab_columns. But that has its own issues, not least that you don't get to validate the insert statement until runtime either, and you still have to figure out how the columns in the two tables align.

The sensible thing to do is take the one-time hit of exploding the * in your code. You don't have to manually type all the columns names; you can generate them from a query against user_tab_columns and cut-and-paste into your procedure. Maintenance then involves remember to add future new columns to the query, if they are required. You could potentially partially script that - e.g. you could generate a trigger that populates a history table, but probably isn't suitable in the middle of a procedure.


As Justin Cave pointed, Oracle 12c introduced invisible columns which would help you out here, but notice that Tom Kytes's article describes this as a workaround for "application code (waiting to be fixed!)", so you should still fix the * reference properly anyway - this just gives you space to get around to it.

Community
  • 1
  • 1
Alex Poole
  • 183,384
  • 11
  • 179
  • 318
  • Well, that was what I was afraid of. But the `user_tab_columns` will make the task a bit easier. Thanks a lot – Mr. E Jan 22 '16 at 17:05
  • 1
    Since you've given a great rundown of the options, you may want to include the 12.1 trick of making columns invisible and then visible again to reorder columns in the table http://www.oracle.com/technetwork/issue-archive/2014/14-may/o34asktom-2162246.html. – Justin Cave Jan 22 '16 at 18:57
  • @JustinCave - thanks; I'm not sure I can do that justice (I still haven't used 12c, shamefully, and I hadn't seen that change mentioned before). but I imagine I'd upvote an answer explaining it if that link isn't enough. (I like the reference to "poorly coded applications"!) – Alex Poole Jan 22 '16 at 19:24