I would like to export import tables from multiple schemas with DBMS_DATAPUMP API.
EG user1.table1 user2.table2 user3.table3
I give in a parameter the tables like a list with comma separated. 'user1.table1,user2.table2,user3.table3'
After that I store in a table the list of tables.
Then I read in a cursor the content of the table and go through in the cursor with a LOOP and give the schemas and table names one by one.
LOOP
dbms_datapump.metadata_filter(handle => h1, name => 'NAME_EXPR', value => 'IN('table1'));
dbms_datapump.metadata_filter(handle => h1, name => 'SCHEMA_LIST', value => 'IN('user1'));
END LOOP.
The first table is successfully added to the dbms_datapump job, but the second table exit with error.
ORA-39071: Value of SCHEMA_LIST is badly formed.
ORA-00936: missing exprension
I tired to find solutions how to exp/imp with DBMS_DATAPUMP API tables from different schemas but I have found any examples. The examples whih I found only shows if you are exp/imp from one schema.
Thanks in advance
--For Table mode, only a single SCHEMA_EXPR filter is supported. If specified, it must only specify a single schema (for example, 'IN (''SCOTT'')').
DBMS_DATAPUMP.METADATA_FILTER(handle, 'SCHEMA_EXPR', 'IN('||vschemas||')');
--you can enter more than one table name, but no more than 4000 characters (literal limit), including special characters.
DBMS_DATAPUMP.METADATA_FILTER(handle, 'NAME_EXPR', 'IN('||vtables||')', 'TABLE');
Related
I am trying to create an Oracle Spatial index but seeing strange behavior.
I have a table in my schema as follows:
CREATE TABLE "Event" (
"EventID" NUMBER(32,0) GENERATED ALWAYS AS IDENTITY INCREMENT BY 1 START WITH 1 NOT NULL,
"Name" NVARCHAR2(30),
"Location" "SDO_GEOMETRY" NOT NULL,
CONSTRAINT "PK_EVENT" PRIMARY KEY ("EventID")
) ;
This works fine and I know I have to create an entry in user_sdo_geom_metadata, that works as you would expect with the following:
insert into user_sdo_geom_metadata (table_name,column_name,diminfo,srid) values ('Event','Location',
sdo_dim_array(sdo_dim_element('X',-180.0,180.0, 0.005),sdo_dim_element('Y',-90.0,90.0, 0.005)), 4326);
This reports success and when I do a select on user_sdo_geom_metadata I see the row. However, when I try to create the spatial index with:
CREATE INDEX "EVINDEX" ON "Event" ("Location") INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2
I get the following error:
SQL Error [29855] [99999]: ORA-29855: error occurred in the execution of ODCIINDEXCREATE routine
ORA-13203: failed to read USER_SDO_GEOM_METADATA view
ORA-13203: failed to read USER_SDO_GEOM_METADATA view
ORA-06512: at "MDSYS.SDO_INDEX_METHOD_10I", line 10
The weird thing is the Index looks like it's been created.
select * from all_indexes where table_name='Event';
Shows the index??? The other odd thing is when I do a select * on ALL_SDO_GEOM_METADATA, no rows are returned??? I'm connecting as a user with almost every privilege and role but not as SYSDBA. I can't get my head around this one.
UPDATE
Incredibly, this seems to be a case sensitivity issue. If you change the table and column names to all UPPERCASE it works. It seems my neverending disappointment in Oracle has a whole new chapter. Going to try to struggle through this somehow, but like most things with Oracle, it's one unrelenting slog to get anything done :(
The documentation says:
The table name cannot contain spaces or mixed-case letters in a quoted string when inserted into the USER_SDO_GEOM_METADATA view, and it cannot be in a quoted string when used in a query (unless it is in all uppercase characters).
and
The column name cannot contain spaces or mixed-case letters in a quoted string when inserted into the USER_SDO_GEOM_METADATA view, and it cannot be in a quoted string when used in a query (unless it is in all uppercase characters).
However, it also says:
All letters in the names are converted to uppercase before the names are stored in geometry metadata views or before the tables are accessed. This conversion also applies to any schema name specified with the table name.
which you can see if you query the user_sdo_geom_metadata view after your insert; the mixed-case names have become uppercase EVENT and LOCATION.
But then:
Note: Letter case conversion does not apply if you use mixed case (“CamelCase”) names enclosed in quotation marks. However, be aware that many experts recommend against using mixed-case names.
And indeed, rather unintuitively, it seems to work if you include the quotes in the user_sdo_geom_metadata insert:
insert into user_sdo_geom_metadata (table_name,column_name,diminfo,srid)
values (
'"Event"',
'"Location"',
sdo_dim_array(sdo_dim_element('X',-180.0,180.0, 0.005),
sdo_dim_element('Y',-90.0,90.0, 0.005)), 4326
);
db<>fiddle
So it appears that the values from the view are at some point concatenated into a dynamic SQL statement, which would explain some of the behaviour.
I have a question concerning the For all Entries statement in ABAP.
I know that it functions like a Select Distinct and deletes duplicate entries.
In my case, I want to write a validation for table inputs. As you can enter more than one line, I have to check every single one of them.
Loop with Select is not an Option. The alternative is For all Entries. Sadly if f.e. the same company code needs to be validated, FoE just gives back one entry. So I have no chance to identify where the error was (if there is one).
Here is the Code for the validation:
LOOP AT extract.
IF <xact> NE empty.
READ TABLE total WITH KEY <vim_xextract_key>.
IF sy-subcs EQ 0.
MOVE <vim_total_struc> TO ls_y.
APPEND ls_y TO lt_y.
ENDIF.
ENDIF.
ENDLOOP.
SELECT bukrs
FROM t001
FOR ALL ENTRIES IN #lt_y
WHERE bukrs = #lt_y-bukrs
INTO TABLE #DATA(lt_check_bukrs).
IF lt_check_bukrs IS INITIAL.
MESSAGE 'Error in company code' TYPE 'S' DISPLAY LIKE 'E'.
vim_abort_saving = abap_true.
ENDIF.
Maybe one of you has an approach or an idea.
Thank you for all answers!
Considering that the company code table should not be too long (in any sanely configured system), I would load it into the application server and do the comparison on the ABAP layer instead of the database layer.
SELECT bukrs
FROM t001
INTO TABLE #DATA(lt_all_bukrs).
LOOP AT lt_check_bukrs REFERENCE INTO DATA #(lr_check_bukrs).
IF NOT line_exists( lt_all_bukrs[ lr_check_burks->bukrs ] )
MESSAGE |Document { lv_check_bukrs->belnr } has invalid company code { lr_check_burks->bukrs }| TYPE 'S' DISPLAY LIKE 'E'.
ENDIF.
ENLOOP.
In a different case where this is not viable because the table you want to compare with is so large it would cause a TSV_TNEW_PAGE_ALLOC_FAILED, then I would go back to where you acquired the original data and perform an OUTER JOIN with the comparison table:
SELECT bkpf~opbel,
bkpf~bukrs
FROM bseg
LEFT OUTER JOIN t001 ON bkpf-burks = t001~bukrs
INTO TABLE
WHERE t001~bukrs IS NULL.
The result table should be all financial document numbers with invalid company codes.
Should this also be impossible because the source data doesn't come from the database (manual entry, read from a file, received from a webservice, whatever...) then the last option would be to pass that data to an ABAP-Managed Database Procedure. Because SQLScript can do JOINs between database tables and tables in memory. But that does require that you are using a SAP HANA database.
I need to mask first and last name. Our requirement is to use the first name only. How can I access the FIRST_NM field when masking the LAST_NM?
LAST_NM=substr(FIRST_NM,1,4)||'LAST'
select T.EE_FIRST_NM, T.EE_LAST_NM from MY_TABLE
Original:
Lakshmanan Ramaswamy
Expected Result:
LaksFIRST LaksLAST
Looks like REMAP_DATA is available from Oracle 11g on. The issue is the REMAP_DATA parameter takes one column as input and a PL/SQL package/function to process that data; so you wouldn't really be able to figure out what first name goes with what last name. There is a good DataPump REMAP_DATA PDF on a sample package & function would work; but it won't solve your problem.
What you could do, depending on your Oracle version, is define a virtual column named LAST_NAME_MASKED on your MY_TABLE that contains a function to do your substr, and then exclude the LAST_NM column from the DataPump export.
One of my columns is called from. I can't change the name because I didn't make it.
Am I allowed to do something like SELECT from FROM TableName or is there a special syntax to avoid the SQL Server being confused?
Wrap the column name in brackets like so, from becomes [from].
select [from] from table;
It is also possible to use the following (useful when querying multiple tables):
select table.[from] from table;
If it had been in PostgreSQL, use double quotes around the name, like:
select "from" from "table";
Note: Internally PostgreSQL automatically converts all unquoted commands and parameters to lower case. That have the effect that commands and identifiers aren't case sensitive. sEleCt * from tAblE; is interpreted as select * from table;. However, parameters inside double quotes are used as is, and therefore ARE case sensitive: select * from "table"; and select * from "Table"; gets the result from two different tables.
These are the two ways to do it:
Use back quote as here:
SELECT `from` FROM TableName
You can mention with table name as:
SELECT TableName.from FROM TableName
While you are doing it - alias it as something else (or better yet, use a view or an SP and deprecate the old direct access method).
SELECT [from] AS TransferFrom -- Or something else more suitable
FROM TableName
Your question seems to be well answered here, but I just want to add one more comment to this subject.
Those designing the database should be well aware of the reserved keywords and avoid using them. If you discover someone using it, inform them about it (in a polite way). The keyword here is reserved word.
More information:
"Reserved keywords should not be used
as object names. Databases upgraded
from earlier versions of SQL Server
may contain identifiers that include
words not reserved in the earlier
version, but that are reserved words
for the current version of SQL Server.
You can refer to the object by using
delimited identifiers until the name
can be changed."
http://msdn.microsoft.com/en-us/library/ms176027.aspx
and
"If your database does contain names
that match reserved keywords, you must
use delimited identifiers when you
refer to those objects. For more
information, see Identifiers (DMX)."
http://msdn.microsoft.com/en-us/library/ms132178.aspx
In Apache Drill, use backquotes:
select `from` from table;
If you ARE using SQL Server, you can just simply wrap the square brackets around the column or table name.
select [select]
from [table]
I have also faced this issue.
And the solution for this is to put [Column_Name] like this in the query.
string query= "Select [Name],[Email] from Person";
So it will work perfectly well.
Hi I work on Teradata systems that is completely ANSI compliant. Use double quotes " " to name such columns.
E.g. type is a SQL reserved keyword, and when used within quotes, type is treated as a user specified name.
See below code example:
CREATE TABLE alpha1
AS
(
SEL
product1
type_of_product AS "type"
FROM beta1
) WITH DATA
PRIMARY INDEX (product1)
--type is a SQL reserved keyword
TYPE
--see? now to retrieve the column you would use:
SEL "type" FROM alpha1
I ran in the same issue when trying to update a column which name was a keyword. The solution above didn't help me. I solved it out by simply specifying the name of the table like this:
UPDATE `survey`
SET survey.values='yes,no'
WHERE (question='Did you agree?')
The following will work perfectly:
SELECT DISTINCT table.from AS a FROM table
Some solid answers—but the most-upvoted one is parochial, only dealing with SQL Server. In summary:
If you have source control, the best solution is to stick to the rules, and avoid using reserved words. This list has been around for ages, and covers most of the peculiarities. One tip is that reserved words are rarely plural—so you're usually safe using plural names. Exceptions are DIAGNOSTICS, SCHEMAS, OCTETS, OFFSETS, OPTIONS, VALUES, PARAMETERS, PRIVILEGES and also verb-like words that also appear plural: OVERLAPS, READS, RETURNS, TRANSFORMS.
Many of us don't have the luxury of changing the field names. There, you'll need to know the details of the RDBM you're accessing:
For SQL Server use [square_braces] around the name. This works in an ODBC connection too.
For MySQL use `back_ticks`.
Postgres, Oracle and several other RDBMs will apparently allow "double_quotes" to be used.
Dotting the offending word onto the table name may also work.
You can put your column name in bracket like:
Select [from] from < ur_tablename>
Or
Put in a temprary table then use as you like.
Example:
Declare #temp_table table(temp_from varchar(max))
Insert into #temp_table
Select * from your_tablename
Here I just assume that your_tablename contains only one column (i.e. from).
In MySQL, alternatively to using back quotes (`), you can use the UI to alter column names. Right click the table > Alter table > Edit the column name that contains sql keyword > Commit.
select [from] from <table>
As a note, the above does not work in MySQL
Judging from the answers here and my own experience. The only acceptable answer, if you're planning on being portable is don't use SQL keywords for table, column, or other names.
All these answers work in the various databases but apparently a lot don't support the ANSI solution.
Simple solution
Lets say the column name is from ; So the column name in query can be referred by table alias
Select * from user u where u.from="US"
In Oracle SQL Developer, pl/sql you can do this with double quotes but if you use double quotes you must type the column names in upper case. For example, SELECT "FROM" FROM MY_TABLE
I need to work with a SQL result set in order to do some processing for each column (medians, standard deviations, several control statements included)
The SQL is dynamic so I don't know the number of columns, rows.
First I tried to use temporary tables, views, etc to store the results, however I did not manage to overcome the 30 character limit of Oracle columns when using the below sql:
create table (or view or global temporary table) as select * from (
SELECT
DMTTBF_MAT_MATURATO_BILL_POS.MAT_V_COD_ANNOMESE,
SUM(DMTTBF_MAT_MATURATO_BILL_POS.MAT_N_NUM_EVENTI_CHZ +DMTTBF_MAT_MATURATO_BILL_POS. MAT_N_NUM_EVENTI) <-- exceeds the 30 character limit
FROM DMTTBF_MAT_MATURATO_BILL_POS
WHERE DMTTBF_MAT_MATURATO_BILL_POS.MAT_V_COD_ANNOMESE >= '201301'
GROUP BY DMTTBF_MAT_MATURATO_BILL_POS.MAT_V_COD_ANNOMESE
)
Second choice was to use some PL/SQL types to store the entire table information, so I could call it like in other programming languages (e.g. a matrix result[i][j]) but I could not find anything similar.
Third variant, using files for reading and writing: i did not try it yet; i'm still expecting a more elegant pl/sql solution
It's possible that I have the wrong approach here so any advice is more than welcome.
UPDATE: Modifying the input SQL is not an option. The program has to accept any select statement.
Note that you can alias both tables and fields. Using a table alias keeps references to it from producing walls of text in the query. Using one for a field gives it a new name in the output.
SELECT A.LONG_FIELD_NAME_HERE AS SHORTNAME
FROM REALLY_LONG_TABLE_NAME_HERE A
The auto naming adds _1 and _2 etc to differentiate the same column name coming from different table references. This often puts a field already borderline over the limit. Giving the fields names yourself bypasses this.
You can put the alias also in dynamic SQL:
sqlstr := 'create table (or view or global temporary table) as select * from (
SELECT
DMTTBF_MAT_MATURATO_BILL_POS.MAT_V_COD_ANNOMESE,
SUM(DMTTBF_MAT_MATURATO_BILL_POS.MAT_N_NUM_EVENTI_CHZ + DMTTBF_MAT_MATURATO_BILL_POS.MAT_N_NUM_EVENTI) AS '||SUBSTR('SUM(DMTTBF_MAT_MATURATO_BILL_POS.MAT_N_NUM_EVENTI_CHZ +DMTTBF_MAT_MATURATO_BILL_POS.MAT_N_NUM_EVENTI)', 1, 30)
||' FROM DMTTBF_MAT_MATURATO_BILL_POS
WHERE DMTTBF_MAT_MATURATO_BILL_POS.MAT_V_COD_ANNOMESE >= ''201301''
GROUP BY DMTTBF_MAT_MATURATO_BILL_POS.MAT_V_COD_ANNOMESE
)'