I am trying to code a sqlldr.ctl file WHEN Clause to limit the records imported to those matching a portion of the current Schema's name.
The code I have (which does NOT work) is:
LOAD DATA
TRUNCATE INTO TABLE TMP_PRIM_ACCTS
when REGION_NUM = substr(user,-3,3)
Fields terminated by "|" Optionally enclosed by '"'
Trailing NULLCOLS
( PORTFOLIO_ACCT,
PRIMARY_ACCT_ID NULLIF (PRIMARY_ASSET_ID="NULL"),
REGION_NUM NULLIF (PARTITION_NUM="NULL")
)
sqlldr returns:
SQL*Loader-350: Syntax error at line 3.
Expecting quoted string or hex identifier, found "substr".
when PARTITION_NUM = substr(user,-3,3)
I cannot put single quotes around "user", because that turns it into the literal string "user". Can anyone explain how I can reference the "active" User in this WHEN Clause?
Thank you!
Can you try something like this? (now I can't make test with SQLLDR, but this is syntax I used for changing values):
when REGION_NUM = "substr(:user,-3,3)"
It doesn't look like you can. The documentation only shows fixed values:
Trying to use an expression in when that clause (or in nullif; thought I'd try to see if you could cause a rejection based on null PK value) you just see the literal value in the log:
Table TMP_PRIM_ACCTS, loaded when REGION_NUM = 0X73756273747228757365722c2d332c3329(character 'substr(user,-3,3)')
which is sort of what you referred when you said you couldn't quote user, but you'd have to quite the whole thing anyway. Using :user doesn't work either, the colon is seen as just another character, it doesn't try to find a column called user instead.
The simplest approach may be to pre-process the data file and remove any rows which don't match the pattern (e.g. via a regex). That would actually be slightly easier if you used an external table instead of SQL*Loader.
Alternatively, generate your control file and embed the correct literal value based on the user you'll connect as.
Related
I am trying to load data into Oracle database using sqlloader,
My data looks like following.
1|2|3|4|5|6|7|8|9|10
I do not want to load first and last column into table,
I want to load 2|3|4|5|6|7|8|9 into one field.
The table I am trying to load into has only one filed named 'field1'.
If anyone has this kind of experience, could you give some advice?
I tried BOUNDFILLER, FILLER and so on, I could not make it.
Help me. :)
Load the entire row from the file into a BOUNDFILLER, then extract the part you need into the column. You have to tell sqlldr that the field is terminated by the carriage return/linefeed (assuming a Windows OS) so it will read the entire line from the file as one field. here the whole line from the file is read into "dummy" as BOUNDFILLER. "dummy" does not match a column name, and it's defined as BOUNDFILLER anyway, so the whole row is "remembered". The next line in the control file starts with a column that DOES match a column name, so sqlldr attempts to execute the expression. It extracts a substring from the saved "dummy" and puts it into the "col_a" column.
The regular expression in a nutshell returns the part of the string after but not including the first pipe, and before but not including the last pipe. Note the double backslashes. In my environment anyway, when using a backslash to take away the special meaning of the pipe (not needed when between the square brackets) it gets stripped when passing from sqlldr to the regex engine so two backslashes are required in the control file
(normally a pipe symbol is a logical OR) so one gets through in the end. If you have trouble here, try one backslash and see what happens. Guess how long THAT took me to figure out!
load data
infile 'x_test.dat'
TRUNCATE
into table x_test
FIELDS TERMINATED BY x'0D0A'
(
dummy BOUNDFILLER,
col_a expression "regexp_substr(:dummy, '[^|]*\\|(.+)\\|.*', 1, 1, NULL, 1)"
)
EDIT: Use this to test the regular expression. For example, if there is an additional pipe at the end:
select regexp_substr('1|2|3|4|5|6|7|8|9|10|', '[^|]*\|(.+)\|.*\|', 1, 1, NULL, 1)
from dual;
2nd edit: For those uncomfortable with regular expressions, this method uses nested SUBSTR and INSTR functions:
SQL> with tbl(str) as (
select '1|2|3|4|5|6|7|8|9|10|' from dual
)
select substr(str, instr(str, '|')+1, (instr(str, '|', -1, 2)-1 - instr(str
, '|')) ) after
from tbl;
AFTER
---------------
2|3|4|5|6|7|8|9
Deciding which is easier to maintain is up to you. Think of the developer after you and comment at any rate! :-)
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'm trying to call a function(ORA_HASH) inside sqlldr but I'm not able to achive the target.
Data File
abc.txt
AKY,90035,"G","DP",20150121,"",0,,,,,,"","E8BD4346-A174-468B-ABC2-1586B81A8267",1,17934,5099627512855,"TEST of CLOROM","",14.00,"",14.00,17934,5099627512855,"TEST of CLOROM",14.00,"ONE TO BE T ONE",344,0,"98027f93-4f1a-44b2-b609-7ffbb041a375",,,AKY8035,"Taken Test","L-20 Shiv Lok"
AKY,8035,"D","DP",20150121,"",0,,,,,,"","E8BD4346-A174-468B-ABC2-1586B81A8267",2,17162,5099627885843,"CEN TESt","",15.00,"",250.00,17162,5099627885843,"CEN TESt",15.00,"ONE TDAILY",3659,0,"09615cc8-77c9-4781-b51f-d44ec85bbe54",,,LLY8035,"Taken Test","L-20 Shiv Lok"
Control file
cnt_file.ctl
load data
into table Table_XYZ
fields terminated by "," optionally enclosed by '"'
F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,F16,F17,F18,F19,F20,F21,F22,F23,F24,F25,F26,F27,F28,F29,F30,F31 ORA_HASH(CONCAT(F2,F5,F6,F9,F10,F12,F13,F14,F15,F16,F17,F19,F21,F22)),F32 ORA_HASH(CONCAT(f23,H24,F7,F8,F3)),F33,F34,F35
sqlldr "xxxxx/yyyyy" control=cnt_file.ctl data=abc.txt
whenever I'm executing sqlldr from Linux box I'm getting below error
SQL*Loader-350: Syntax error at line 4.
Expecting "," or ")", found "ORA_HASH".
F29,F30,F31,KEY_CLMNS_HASH ORA_HASH(CONCAT( F2,F5
^
Any idea
You might consider using a virtual column on the table to which you are loading the data.
For columns which are deterministically based on other column values in the same row, that usually ends up being a more simple solution than anything involving SQL*Loader.
You're doing a few things wrong. The immediate error is because the Oracle function call has to be enclosed in double quotes:
...,F31 "ORA_HASH(CONCAT(F2,F5,F6,...))",...
The second issue is that the concat function only takes two arguments, so you would either have to nest (lots of) concat calls, or more readably use the concatenation operator instead:
...,F31 "ORA_HASH(F2||F5||F6||...)",...
And finally you need to prefix the field names inside your function call with a colon:
...,F31 "ORA_HASH(:F2||:F5||:F6||...)",...
This is explained in the documentation:
The following requirements and restrictions apply when you are using SQL strings:
...
The SQL string must be enclosed in double quotation marks.
And
To refer to fields in the record, precede the field name with a colon (:). Field values from the current record are substituted. A field name preceded by a colon (:) in a SQL string is also referred to as a bind variable. Note that bind variables enclosed in single quotation marks are treated as text literals, not as bind variables.
I am currently using DB2 . I do not know much about load statement.
I am using this query to load data..
LOAD FROM "IXAC.CSV" OF DEL METHOD P ('IX',1,2,3,4,) MESSAGES
"SYAC.MSG" INSERT INTO SYNC.AC_COUNT ( "TYPE", AC1, AC2, AC3,
AC4 ) ; COMMIT;
In "IXAC.CSV" there are 4 int values separated with comma. My problem is that how can i insert 'IX' with load statement as a constant with each row insert.
I tried this but not found any success. I am newer in database.
Help me ..
Thanks in advance ...
Change your table definition in the database to have a default value for the column 'IX' (it looks like you want "TYPE"?).
Then do the load as normal, leaving out the IX column.
if you are able to edit the .csv file a workaround is that you can use a text editor (such as ultra edit) that supports wildcards or regular expressions in its find/replace feature and replace each carriage return/line feed with a CR/LF followed by "IX," (quotes optional depending on if you want to specify a text delimiter on insert). then your .csv file will have all your data.
I have a little silly question. I have installed a PostgreSQL DB Server, but when I run query, there is a problem with column identifier without quotes. I don't know why the quotes around identifiers are needed. My query:
SELECT vc."CAR_ID"
FROM "VEL_CAR" vc, "VEL_DRIVER" vd, "VEL_DRIVER_CAR" vdc
WHERE vc."CAR_ID" = vdc."CAR_ID" and
vdc."DRIVER_ID" = vd."DRIVER_ID";
My practice from Oracle DB is not to use ". So in Oracle:
SELECT vc.CAR_ID
FROM VEL_CAR vc, VEL_DRIVER vd, VEL_DRIVER_CAR vdc
WHERE vc.CAR_ID = vdc.CAR_ID and
vdc.DRIVER_ID = vd.DRIVER_ID;
When I run this query without quotes in PostgreSQL it throws error about syntax:
ERROR: column vc.car_id does not exist
LINE 1: SELECT vc.CAR_ID
Do you know why?
--SOLVED--
Thank you, now I solved the problem! It was about table creation. I created table objects using pgAdminIII and i wrote table name and column names uppercased. pgAdminIII created query with quotas - because of the names was uppercased. So query had to be written with quotas.
When you create your tables using double quotes, column and table names become case sensitive. So "car_id" is a different name than "CAR_ID"
You need to create your tables without using double quotes, then the names are not case sensitive: car_id is the same as CAR_ID (note the missing quotes!)
See the manual for details:
http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
Edit:
Oracle behaves just the same way. The only difference is that Oracle stores names in upper case and Postgres stores them in lower case. But the behaviour when using quotes is identical.
From Postgres documentation :
Quoting an identifier also makes it case-sensitive, whereas unquoted names are always folded to lower case. For example, the identifiers FOO, foo, and "foo" are considered the same by PostgreSQL, but "Foo" and "FOO" are different from these three and each other. (The folding of unquoted names to lower case in PostgreSQL is incompatible with the SQL standard, which says that unquoted names should be folded to upper case. Thus, foo should be equivalent to "FOO" not "foo" according to the standard. If you want to write portable applications you are advised to always quote a particular name or never quote it.)
Seems to me that the table vc does not have a column named car_id. Are you sure it is there? Do \d vel_car to see the structure of the table.
The quotes are optional and you can usually skip them.