What is the use of $$ sign in table name in Oracle Database - sql

I get to maintain a application which use $$ sign as prefix and suffix to some word in the table create statement - Oracle DB. like
create table $$temp$$(id int)
For testing purpose I ran the statement in SQL plus but it threw invalid character error and so I had to remove $$ sign and then it ran as expected.
Is there a specific use for $$? some thing related to session ?

Is there a specific use for $$
No there is not. Dynamic performance views, however, have one dollar sign ($) in their names, v$sql, for example. It's Oracle's choice to name them that way.
You won't be able create a table, which name starts with dollar sign($), simply because any non-quoted identifier should begin with an alphabetic character. You can however force Oracle to accept an identifier that begins with a non-alphabetic character if you enclose it with double quotation marks, like so
create table "$$temp$$"(
id int
)
but it should be noted that when you created a table using double quotation marks, you made that table name case-sensitive (unless you didn't type the table name in uppercase) and would always have to use double quotation marks when referencing that table.

You can create, and later drop, the table with nonstandard characters by using double(!) quotes around the table name: create table "$$tmp$$"(id int). And no, the $ doesn't have any special meaning, except that it shouldn't be used by the user, because various internal tables have names that contain a $ (think v$session). The $ is supposed to avoid name conflicts.

Related

How to represent double quotes in dynamic PL/pgsql ALTER TABLE statement

I find myself in a position that I'm sure many others have before. I generated my PostgreSQL schema using a generator and now I'm in production(!), I realise I should really try to remove the double quotes from the table and column names that the generator added i.e.
CREATE TABLE "myschema"."mytable" (....
should have been
CREATE TABLE myschema.mytable (....
I'm writing a PL/pgsql function to loop through information_schema.tables and information_schema.columns and then to execute ALTER TABLE statements to drop the doube quotes.
What I can't grasp from the documentation and searhcing is how to issue that statement.
I know it's an EXECUTE I need but can someone help me with the syntax to rename "mytable" to mytable using that. I'm lost with $$ and format() and quote_ident() and think I'm overcomplicating how to indicate that my original table names will have double quotes.
The double-quotes in your examples are not part of the names, just decorators to preserve original spelling of identifiers. See:
Are PostgreSQL column names case-sensitive?
While working with lower-case, legal identifiers (like your examples suggest), those double-quotes are purely optional. Add them or leave them.
If you've been unwise enough to create objects with illegal names or with mixed case, those double-quotes are required at all times. The cure is to stick to legal, lower-case identifiers.
Start by reading the manual about identifiers.

Cannot create stored procedure to insert data: type mismatch for serial column

CREATE TABLE test ( id serial primary key, name text );
CREATE OR REPLACE PROCEDURE test_insert_data( "name" text)
LANGUAGE SQL
AS $$
INSERT INTO public.test values("name")
$$;
Error & Hint:
column "id" is of type integer but expression is of type character varying
LINE 4: INSERT INTO public.test values("name")
^
HINT: You will need to rewrite or cast the expression.
I followed this tutorial: https://www.enterprisedb.com/postgres-tutorials/10-examples-postgresql-stored-procedures.
Obviously, I don't need to attach the column id for inserting.
There is no quoting issue, like comments would suggest.
And the linked tutorial is not incorrect. (But still bad advise.)
The missing target column list is the problem.
This would work:
CREATE OR REPLACE PROCEDURE test_insert_data("name" text)
LANGUAGE sql AS
$proc$
INSERT INTO public.test(name) -- !! target column list !!
VALUES ("name");
$proc$;
(For the record, since "name" is a valid identifier, all double quotes are just noise and can (should) be omitted.)
If you don't specify the target column(s), Postgres starts to fill in columns from left to right, starting with id in your case - which triggers the reported error message.
(The linked tutorial also provides an ID value, so it does not raise the same exception.)
Even if it would work without explicit target column list, it's typically still advisable to add one for persisted INSERT commands. Else, later modifications to the table structure can break your code silently. With any bad luck in a way you'll only notice much later - like filling in the wrong columns without raising an error.
See:
SQL INSERT without specifying columns. What happens?
Inserting into Postgres within a trigger function
Aside: I would never use "name" as column name. Not even in a generic tutorial. That's not helpful. Any column name is a "name". Use meaningful identifiers instead.

alter table with space in name

I have a table with a space in the name generated by a system.
I am trying to alter the table name to remove the space so that it can be processed by a library the pre-exists.
I am trying:
ALTER TABLE 'My Table'
RENAME TO 'MyTable';
I have also tried double quotes, no luck.
Any pointers?
[This will not work in MS-Access. Tables cannot be renamed in Access. Not clear if original question applied to MS Access.]
Square brackets:
ALTER TABLE [My Table]
RENAME TO [MyTable];
Square brackets can't enclose the entire object "path" so this won't work:
ALTER TABLE [MyDatabase.dbo.My Table]
but this will
ALTER TABLE [MyDatabase].[dbo].[My Table]
For MySQL, single quotes, double quotes or brackets did NOT work for me. Only backticks (aka backquotes) worked.
So, try this:
ALTER TABLE `My Table`
RENAME TO MyTable;
[My Table]
You can use square brackets in SQL to get around this.
It has many functions, you can use keywords in tables, put spaces and periods in table names or schemas, etc.
For example you can have the schema [Work.Employees]. With the square bracket it would be [Work.Employees].Addresses (schema, table). However, if you forget the brackets it will attempt to find the database Work -> schema Employees -> Table Addresses.
However, it is generally good practice to avoid doing any of the above :)
This is one of those things that is a lot easier to achieve using the Access GUI!
To do the same in SQL DDL you must 'clone' the table, for which you must already have knowledge of all the attribute names, types, constraints, etc, noting it may have features that are not creatable via SQL DDL e.g. Validation Rules. Then you need to populate it using the original table. The you drop the original. Phew!

pl/sql dollar operator?

I encountered the following ddl in a pl/sql script this morning:
create index genuser.idx$$_0bdd0011
...
My initial thought was that the index name was generated by a tool...but I'm also not a pl/sql superstar so I could very well be incorrect. Does the double dollar sign have any special significance in this statement?
No special meaning or significance.
SQL> create table t (col number)
2 /
Table created.
SQL> create index idx$$_0bdd0011 on t(col)
2 /
Index created.
Note: CREATE INDEX is a DDL statement which is usually executed in a SQL script, not in PL/SQL.
Your initial thought seems to be correct. That would look to be an index name generated by a tool (but not assigned by Oracle because an index name wasn't specified). Dollar signs don't have any particular meaning other than being valid symbols that are rarely used by human developers and so are handy to reduce the risk that a system-generated name conflicts with a human-generated name.
Regardless of where he name came from, it's contrary to Oracle's documented advice: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements008.htm#SQLRF00223
Oracle strongly discourages you from using $ and # in nonquoted identifiers

Oracle why does creating trigger fail when there is a field called timestamp?

I've just wasted the past two hours of my life trying to create a table with an auto incrementing primary key bases on this tutorial, The tutorial is great the issue I've been encountering is that the Create Target fails if I have a column which is a timestamp and a table that is called timestamp in the same table...
Why doesn't oracle flag this as being an issue when I create the table?
Here is the Sequence of commands I enter:
Creating the Table:
CREATE TABLE myTable
(id NUMBER PRIMARY KEY,
field1 TIMESTAMP(6),
timeStamp NUMBER,
);
Creating the Sequence:
CREATE SEQUENCE test_sequence
START WITH 1
INCREMENT BY 1;
Creating the trigger:
CREATE OR REPLACE TRIGGER test_trigger
BEFORE INSERT
ON myTable
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT test_sequence.nextval INTO :NEW.ID FROM dual;
END;
/
Here is the error message I get:
ORA-06552: PL/SQL: Compilation unit analysis terminated
ORA-06553: PLS-320: the declaration of the type of this expression is incomplete or malformed
Any combination that does not have the two lines with a the word "timestamp" in them works fine. I would have thought the syntax would be enough to differentiate between the keyword and a column name.
As I've said I don't understand why the table is created fine but oracle falls over when I try to create the trigger...
CLARIFICATION
I know that the issue is that there is a column called timestamp which may or may not be a keyword. MY issue is why it barfed when I tried to create a trigger and not when I created the table, I would have at least expected a warning.
That said having used Oracle for a few hours, it seems a lot less verbose in it's error reporting, Maybe just because I'm using the express version though.
If this is a bug in Oracle how would one who doesn't have a support contract go about reporting it? I'm just playing around with the express version because I have to migrate some code from MySQL to Oracle.
There is a note on metalink about this (227615.1) extract below:
# symptom: Creating Trigger fails
# symptom: Compiling a procedure fails
# symptom: ORA-06552: PL/SQL: %s
# symptom: ORA-06553: PLS-%s: %s
# symptom: PLS-320: the declaration of the type of this expression is incomplete or malformed
# cause: One of the tables being references was created with a column name that is one of the datatypes (reserved key word). Even though the field is not referenced in the PL/SQL SQL statements, this error will still be produced.
fix:
Workaround:
1. Rename the column to a non-reserved word.
2. Create a view and alias the column to a different name.
TIMESTAMP is not listed in the Oracle docs as a reserved word (which is surprising).
It is listed in the V$RESERVED_WORDS data dictionary view, but its RESERVED flag is set to 'N'.
It might be a bug in the trigger processing. I would say this is a good one for Oracle support.
You've hinted at the answer yourself. You're using timestamp as a column name but it's also a keyword. Change the column name to something else (eg xtimestamp) and the trigger compiles.
Well, I'm not totally sure about it, but I think this happens because the SQL code used to manipulate and access database objects is interpreted by some interpreter different form the one used to interpret PL/SQL code.
Have in mind that SQL an PL/SQL are different things, and so they are processed differently. So, I think there is some error in one interpreter, just not sure which one is.
Instead of having Oracle maintain a view, use EXECUTE IMMEDIATE (i.e. if 'Rename the column to a non-reserved word' is not an option.
You can execute via EXECUTE IMMEDIATE. IT's not better way but work's and avoid column rename.
In my case rename column will be a caotic way