Incorrect syntax near ')' - installshield-2009

I have a BasicMSI project (Installshield 2009) that runs a SQL script during the installation process.
During the installation I receive the following error.
Error 27506.Error executing SQL script {SCRIPTNAME}. Line 352. Incorrect syntax near ')'. (102)
The problem is that I don't have any ')' at line 352 of the script and also the script works without any problems if I run it with SQL Management Studio Express.
Can anyone tell me what is the problem and how can I fix it?
Thanks.
PS. I cannot set the script error handling option to "On Error, Goto Next Statement" because therefor it will not create some of my foreign keys.
IF NOT EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[TRIGGER_NAME]'))
EXEC dbo.sp_executesql #statement = N'
CREATE TRIGGER [dbo].[TRIGGER_NAME]
ON [dbo].[TABLE_NAME] -- LINE: 352
INSTEAD OF INSERT
AS
BEGIN
DECLARE #Count INT;
SET #Count = (SELECT COUNT([Name])
FROM TABLE_NAME
WHERE IsDeleted = 0 AND [Name] IN (SELECT [Name] FROM INSERTED));
IF #Count > 0
BEGIN
RAISERROR (''Error Message.'', 16, 1);
Rollback;
END
ELSE
BEGIN
INSERT INTO dbo.TABLE_NAME SELECT {Columns} FROM INSERTED;
SELECT CONVERT(BigInt,SCOPE_IDENTITY()) AS [value]
END
END
'
GO

I was getting similar errors (one with ')' as the offending character, one with ';' as the offending character). Then I noticed that when InstallShield imported my scripts, it had changed ">" to ">" and "<" to "<" and "&" to "&". Doing search-and-replace across the imported scripts in the InstallShield script editor for these three substitutions fixed the issue for me.

It seems reasonable that this error might occur if you've written an IN statement, which you populate programmatically, only at runtime some values are missing, resulting in a statement saying "... WHERE x IN()", which is invalid.
This would generate that error, and also, it is an error that could easily appear in one environment but not another. It is hard to give more detail than that without actually seeing the script.

Related

PLS-00103: Encountered the symbol " " when expecting one of the following

For some reason this wont work. I have got it down to the most basic operation to try and troubleshoot.
BEGIN
FOR rec IN (
select REGISTRATION_UID from DIM_REGISTRATION_SET
) 
   LOOP
dbms_output.put_line('Testing 123');
  END LOOP; 
end;
/
My error is as below:
Error starting at line 1 in command:
BEGIN
FOR rec IN (
select REGISTRATION_UID from DIM_REGISTRATION_SET
) 
   LOOP
dbms_output.put_line('Testing 123');
  END LOOP; 
end;
Error report:
ORA-06550: line 4, column 6:
PLS-00103: Encountered the symbol " " when expecting one of the following:
loop
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
You seem to have an unexpected character in your code. If you copy and paste the rendered output from this question then it runs fine. If you copy the question source code (from the edit dialogue) then it gets that error.
Dumping the code (again copied from the source, not the rendering) shows:
select dump('(
select REGISTRATION_UID from DIM_REGISTRATION_SET
) ', 16)
from dual; 
DUMP('(SELECTREGISTRATION_UIDFROMDIM_REGISTRATION_SET) ',16)
--------------------------------------------------------------------------------
Typ=96 Len=73: 28,a,20,20,20,20,20,20,20,20,20,20,73,65,6c,65,63,74,20,52,45,47,
49,53,54,52,41,54,49,4f,4e,5f,55,49,44,20,66,72,6f,6d,20,44,49,4d,5f,52,45,47,49
,53,54,52,41,54,49,4f,4e,5f,53,45,54,a,20,20,20,20,20,20,20,20,29,c2,a0
So the space after the closing parenthesis isn't actually a space, it's Unicode character c2a0, which is a non-breaking space.
The error message shows that too, if you dump that:
select dump ('Encountered the symbol " "', 16) from dual;
DUMP('ENCOUNTEREDTHESYMBOL" "',16)
--------------------------------------------------------------------------------
Typ=96 Len=27: 45,6e,63,6f,75,6e,74,65,72,65,64,20,74,68,65,20,73,79,6d,62,6f,6c
,20,22,c2,a0,22
I would guess you copied that code from somewhere (Word?) and it picked up that character, and it hasn't been translated to a normal space. Just replace it with a space, or remove it as it's redundant whitespace anyway.
Actually, there are several others; two at the start of the LOOP line (followed by two normal spaces), and two immediately before END LOOP; (preceded by two normal spaces), and one after that statement; so those all need to be replaced too. (I'd be tempted to retype the whole thing, but that might not be practical for your full code).

Invalid Number with Substitution Variable

I am having trouble trying to get an input to be accepted as a number variable. Here is the code I have:
ACCEPT clientidnum NUMBER PROMPT 'Enter Client Number(s): '
SELECT * FROM PROD.GS_EXTERNAL_CONTACT#prd1.WORLD
WHERE GEC_GS_EXT_CONTACT_ID IN (SELECT GEC_GS_EXT_CONTACT_ID
FROM PROD.CLIENT#prd1.WORLD a
WHERE CT_CLIENT_ID = to_number(trim(replace('&clientidnum',CHR(13)))) AND
a.GEC_GS_EXT_CONTACT_ID NOT IN (SELECT GEC_GS_EXT_CONTACT_ID
FROM PROD.GS_EXTERNAL_CONTACT b
WHERE a.GEC_GS_EXT_CONTACT_ID= b.GEC_GS_EXT_CONTACT_ID));
And when I run this in SQL Plus, it comes back with the below error:
ERROR at line 4:
ORA-01722: invalid number
Thanks for the assistance! Sorry if this is an easy question, but I'm use to SQL Server and was thrown on Oracle to get some things to work correctly.
Figured it out. SET DEFINE was set to OFF in my glogin.sql script. I added SET DEFINE ON to the script I am running and it works.

how to write a batch file, which runs a PL/SQL block, to tell me many records are inserted/deleted/etc. in a log file?

I have created two batch files to run two separate .sql file in Windows Task Scheduler. The batch file for both looks like this:
sqlplus userid/password#database #C:\XXX.sql>>C:\output.log
echo commit; | userid/password#database
The first .sql file (SQL1) is a PL/SQL block like this:
SET SERVEROUT ON
DECLARE
....
BEGIN
IF ...
....
ELSE
#D:\DM_FIX.sql;
END IF
END
The DM_FIX.sql file is to insert a bunch of records into a table, and it starts with the INSERT command.
The second.sql file is not a block file. It's doing a bunch of DDL/DML comand. the file looks like below:
Truncate Table YYY
Reuse Storage;
Commit;
Insert into Table YYY
Select ... from
Commit;
Delete from Table YYY
where ...
Commit;
When I run the second .sql file, I get an output that indicates "The table has been truncated; #### records are inserted; #### records are deleted..."
But when I run the first, although the PL/SQL procedure is executed successfully, I don't get a line saying how many records are inserted, and I'm trying to figure out a way to do it.
Does any one know what could be the trick?
Thanks!
Revised Answer
As #Alex Poole helpfully pointed out, you can use the # nomenclature in a PL/SQL block from SQL*Plus, as that would load the second file's commands into the block that you're calling it from.
The reason that you're not getting any output is that, as far as SQL*Plus is concerned it's all one command: the SQLPlus block. In order to get output to your log for those commands, you'll need to create it yourself, using DBMS_OUTPUT. You would need to include a line like the one below after each command.
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' rows inserted');
However, you should note that doing this will cause your script to throw errors if it's ever called from outside of a PL/SQL block. My original solution would avoid this restriction, as it eliminates the need to use DBMS_OUTPUT.
Original Answer
I find it difficult to believe that the PL/SQL in the first file is executing successfully. This is because you're mixing SQL*Plus commands with PL/SQL code. They are separate systems - it's like trying to use shell commands natively in a programming language. You should be getting PLS-00103: Encountered the symbol "#" when expecting... from the first file.
SQL*Plus doesn't have conditionals, so, in order to keep the PL/SQL and SQLPlus commands seperate, you'd need to fake it somewhat. I'd suggest putting the file name into a substitution variable, then using that to run a file:
VARIABLE v_my_file_bind varchar2(100)
DECLARE
...
BEGIN
IF ...
...
:v_my_file_bind := 'D:\EMPTY_FILE.sql';
ELSE
:v_my_file_bind := 'D:\DM_FIX.sql';
END IF;
END;
/
COLUMN v_my_file_column new_value my_file_substitution noprint
SELECT :v_my_file_bind v_my_file_column from dual;
#&&my_file_substitution
To show count of modified rows in PL/SQL, use SQL%ROWCOUNT:
begin
insert into my_table ...
select ...
from ...;
dbms_output.put_line('Rows inserted: ' || SQL%ROWCOUNT);
commit;
end;
/
Remember, that SQL%ROWCOUNT variable will reset to 0 after commit.
Documentation: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/sql_cursor.htm

Passing Contents of File as Parameter to Sql*Plus Command

I'm trying to write a sqlplus command that creates a table from a query that is stored in an .sql file.
The particular .sql file that contains the query would be supplied to my sqlplus command as a variable (&v_InputQuery).
I've tried something like this, but it doesn't work.
CREATE TABLE &v_OutputTable AS
(
< &v_InputQuery
)
;
I get an error saying that there's a missing SELECT keyword.
What I'd really like is for &v_InputQuery to be replaced not with the name of the file specified by the user, but with the actual contents of the file. Is there a way to do that?
Thank you very much.
Yes, you can do that. If your query is in a file called v_InputQuery.sql, you can do this:
CREATE TABLE &v_OutputTable AS (
#v_InputQuery.sql
) ;
It's important that the # is the first character on the line. SQL*Plus will read the file and put its contents at that location. So make sure you don't have any terminating characters in the file such as ; or /.
Unfortunately, You cannot create a SQL*Plus command, but instead create a shell script to do it!
Lets say my_script.sh is below
#you can always complete the user interaction at unix/dos
USER=your_user
PASS=your_pass
DB=your_db
OUTPUT_TABLE=$1;
QUERY_FILE=$2;
SELECT_QUERY=`cat $QUERY_FILE`;
sqlplus -S ${USER}/${PASS}#${DB} << !
SET SERVEROUTPUT ON;
VAR EXITCODE NUMBER;
BEGIN
EXECUTE IMMEDIATE ' CREATE TABLE $OUTPUT_TABLE AS $SELECT_QUERY ';
:EXITCODE := SQLCODE;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
:EXITCODE := SQLCODE;
END;
/
exit :EXITCODE
!
Executing the script as below(Depends on OS)
ksh my_script MY_OUTPUT_TABLE my_sql.sql;
Expanding a comment, #MaheswaranRavisankar's approach will work, but the dynamic SQL (i.e. execute immediate) isn't necessary, so the anonymous block isn't necessary either. It can be simplified somewhat to:
USER=your_user
PASS=your_pass
DB=your_db
OUTPUT_TABLE=$1;
QUERY_FILE=$2;
SELECT_QUERY=`cat $QUERY_FILE`;
sqlplus -S ${USER}/${PASS}#${DB} << !
WHENEVER SQLERROR EXIT FAILURE
CREATE TABLE $OUTPUT_TABLE AS $SELECT_QUERY
!
This also allows you to use a query which is already terminated by a ; or /, which the execute immediate version wouldn't like - you just need to decide whether your wrapper script needs one to match what your query files will contain.
Even the whenever ... line isn't vital, but the other answer tried to exit with the error code so I've mimicked that too somewhat. This will always exit with a generic failure status though (1 in Unix, not sure what Windows does). You can then test if it was successful with $? in the script if you want to.
You can exit with the actual SQL error instead of the generic value, by using whenever sqlerror exit sql.sqlcode instead. The problem with doing that is that most (all?) shells limit the return code to the range 0-255, so most errors will wrap and give something unhelpful anyway - a fairly-likely ORA-00955: name is already used by an existing object error would give a shell exit value of 187, for example. And it's possible the wrapped value would be zero, which would mask that an error occurred at all; an also-plausible ORA-01536: space quota exceeded for tablespace '%s' error would give a shell exit code of zero, which is unhelpful. Using exit failure would at least stop that.

Error when trying to load data from Unix script

when i am trying to execute the SQL script from Unix server its showing error but the same SQL i am running from sql navigator its working fine .. kindly help me on it..
INSERT INTO t_csocstudent_course_local
(SELECT tsct.student_id,
tsct.object_lookup_id,
tsct.course_id,
tsct.xcourse_id,
clt.NAME,
tsct.course_type,
FROM temp_stud_course tsct join course_local clt
on tsct.COURSE_ID = clt.COURSE_ID
WHERE TO_CHAR (sc_timestamp, 'YYYYMMDDHH24MISS') >
(SELECT TO_CHAR (MAX (sc_timestamp), 'YYYYMMDDHH24MISS')
FROM t_student_course_local)
AND tsct.xcourse_id IN
('EX1','EX2'));
Error :
Error in loading main table
Enter password:
SP2-0734: unknown command beginning "WHERE TO..." - rest of line ignored.
AND tsct.xcourse_id IN
*
ERROR at line 3:
ORA-00933: SQL command not properly ended
Thanks in advance !!
I can't remember if the Oracle command line client permits extra whitespace linebreaks. Remove the extra linebreak before the WHERE clause.
Update
From the documentation, an empty line terminates a SQL statement by default in SQLplus.
SQLT[ERMINATOR] {;|c|OFF|ON}|
Set the char used to end and execute SQL commands to c.
OFF disables the command terminator - use an empty line instead.
ON resets the terminator to the default semicolon (;).
You can change the behavior to use semicolons instead of empty lines:
SET SQLTERMINATOR ON

Resources