Microsoft ODBC driver for ORacle ORA-12154: TNS could not resolve service name

For some of us whom frequently using MS Access in daily use, encountered an error might be very troublesome.

The problem is like this : I am using MS Access for data analysis and checking and have a connection over the network to Oracle database. My connection was using Microsoft ODBC Driver for Oracle. For some security reason, I need to change the password now. The password changed with no problem but encountered error ORA-12154 when trying to relink the tables.

Error as below:
ODBC--call failed
Microsoft ODBC driver for ORacle ORA-12154: TNS could not resolve service name

Generally, ORA-12154 indicated that the specifying TNS alias is not resolving. Few questions needed to clarify;

  1. Are you using a DSN for your connection to Oracle database? 
  2. If so, what is the TNS alias that you specifying? 
  3. Does that alias exist in your tnsnames.ora file? 
  4. Are there multiple tnsnames.ora files on your machine?

Your should have your tnsnames.ora file when you installing the Oracle client software/driver. If you wondering what is the version of the Oracle client you have installed, the simplest way is to get DOS command prompt and type 'tnsping [service_name]' where [service_name] is TNS alias specified in your DNS.

The ouput of it may look like this:
C:\Users\jcave>tnsping fuddy_duddy
TNS Ping Utility for 64-bit Windows: Version 11.2.0.1.0 - Production on 07-OCT-2
010 08:10:51
Copyright (c) 1997, 2010, Oracle.  All rights reserved.
Used parameter files:
C:\oracle\product\11.1.0\db_1\NETWORK\ADMIN\sqlnet.ora
TNS-03505: Failed to resolve name

The "Used parameter files" line shows you the directory where the TNS related files are stored. A tnsnames.ora and a sqlnet.ora file should be in that directory and it alwasys be there by default. Perhaps you should check the TNS alias name and confirm with your DNS setting.

How to load image files into BLOB column using PL/SQL

Assuming that you have a list of physical images needed to be loaded into Oracle database. And also you have a free text list of the files, perhaps in form of CSV file format.

From above, you may already get the bigger picture of the scenario which you need to execute.

Lets consider this task needed to be execute in Oracle using Oracle procedure.

The PL/SQL

I already prepared the PL/SQL example for this purpose. Check the code below;
CREATE OR REPLACE PROCEDURE PROC_LOAD_IMAGES (FILE_DIR in VARCHAR2 , MYFILE_NAME in VARCHAR2) AS
  -- FILE_DIR is the directory of the flat file and images
  -- MYFILE_NAME is  the flat file name
  F UTL_FILE.FILE_TYPE;
  V_LINE VARCHAR2 (1000);
  V_CACC_OLD_NUM  VARCHAR2(24 BYTE);
  V_IDENT_TYPE    NUMBER(1);
  V_ID_NUMBER     VARCHAR2(20 BYTE);
  V_FILE_NAME     VARCHAR2(80 BYTE);
  V_FILE_BLOB     BLOB;
  V_CLASS         VARCHAR2(1 BYTE);
  lFile           BFILE;
           
BEGIN
    F := UTL_FILE.FOPEN (upper(FILE_DIR), MYFILE_NAME, 'R');
    IF UTL_FILE.IS_OPEN(F) THEN
        LOOP
            BEGIN
            UTL_FILE.GET_LINE(F, V_LINE, 1000);
            IF V_LINE IS NULL THEN
            EXIT;
            END IF;
                --If using piping, change to '[^|]+'
                V_CACC_OLD_NUM := REGEXP_SUBSTR(V_LINE, '[^|]+', 1, 1);
                V_IDENT_TYPE := REGEXP_SUBSTR(V_LINE, '[^|]+', 1, 2);
                V_ID_NUMBER := REGEXP_SUBSTR(V_LINE, '[^|]+', 1, 3);
                V_FILE_NAME := REGEXP_SUBSTR(V_LINE, '[^|]+', 1, 4);
                V_CLASS := REGEXP_SUBSTR(V_LINE, '[^|]+', 1, 5);
             
                INSERT INTO BS_SIGNATURE_IMAGES (CACC_OLD_NUM, IDENT_TYPE, ID_NUMBER, FILE_NAME, CLASS) VALUES( V_CACC_OLD_NUM, V_IDENT_TYPE, V_ID_NUMBER, empty_blob(), V_CLASS) RETURNING FILE_NAME INTO V_FILE_BLOB;
                lFile := BFILENAME(upper(FILE_DIR), V_FILE_NAME);
             
                IF dbms_lob.fileexists(lFile) = 1 THEN      
                    DBMS_LOB.OPEN(lFile, DBMS_LOB.LOB_READONLY);
                    DBMS_LOB.OPEN(V_FILE_BLOB, DBMS_LOB.LOB_READWRITE);
                    DBMS_LOB.LOADFROMFILE(DEST_LOB => V_FILE_BLOB,
                                          SRC_LOB  => lFile,
                                          AMOUNT   => DBMS_LOB.GETLENGTH(lFile));
                    DBMS_LOB.CLOSE(lFile);
                    DBMS_LOB.CLOSE(V_FILE_BLOB);
                END IF;
             
                COMMIT;
                             
            EXIT;
            END;
        END LOOP;
    END IF;
    UTL_FILE.FCLOSE(F);
END;
/
The important portion UTL_FILE function. This is the function to read the file and responsible to load the files into BLOB format into the database.

APEX : Send email with attachment (Part 2)

Please refer to my previous post related to this, here.

Moving forward, by now you should already completed doing these 2 things:
  1. User can insert any attachment into the form
  2. The attachment will be save into my own table within the Oracle database.
So now, the next step is to configure APEX to sent-out email together with the attachment.

The email process must be create at point [Processing > Processes] on [Page Processing] , right after the 'CopyFile' process (refer to my previous post)
  1. Right click on [Processes] > Create
  2. Select [PL/SQL] and Next
  3. Give a name to identify the procesess and click Next
  4. On the [Enter PL/SQL Page Process], paste below code;
DECLARE
    l_id number;
BEGIN
    l_id := APEX_MAIL.SEND( p_to        => 'fred@flintstone.com',
                            p_from      => 'barney@rubble.com',
                            p_subj      => 'APEX_MAIL with attachment',
                            p_body      => 'Please review the attachment.',
                            p_body_html => '<b>Please</b> review the attachment' );
    FOR c1 IN (SELECT filename, blob_content, mime_type
                 FROM attachment_files
                WHERE ID = :P1_YOUR_ID ) loop
    APEX_MAIL.ADD_ATTACHMENT( p_mail_id    => l_id,
                                  p_attachment => c1.blob_content,
                                  p_filename   => c1.filename,
                                  p_mime_type  => c1.mime_type);
    END LOOP;
END;
BEGIN
wwv_flow_mail.push_queue(
   P_SMTP_HOSTNAME => 'localhost',
   P_SMTP_PORTNO => '25'
);
END;
Please see the code and change whenever suit with your table name and page item. For example code below:
FOR c1 IN (SELECT filename, blob_content, mime_type
                 FROM attachment_files
                WHERE ID = :P1_YOUR_ID ) loop
The [attachment_files] comes from my table which I have created previously in so called Part 1.

You can have multiple 'File Browse...'. You may also need to change the PL/SQL code if have more [File Browse]. Do comment below if you still need help.

I will try my best to help. :)


APEX : Send email with attachment

I have found a working solution for sending email with attachment using APEX application. But first, few items have to take note :-
  1. User can insert any attachment into the form
  2. The attachment will be save into my own table within the Oracle database.
User can insert any attachment

This will be require an item named 'File Browse...'. Simply add the item into the page. I assume at this point, you already know how to it. Lets name it as [P1_ATTACHMENT]

Take a look at the [Settings] tab when u edit this item page. The storage type setting can be either two : 1.Table WWV_FLOW_FILES and 2.BLOB column specified in Item Source attribute

I will choose option No.1. Why I did not choose option No.2? As I had mentioned that the attachment will be save into my own table?

I am not expert, perhaps you can correct me if I am wrong, but I think that insert a attachment files into table will require some additional coding when we want to execute it in APEX environment.

One more reason is, I already has define one table to fetch row in the [Processes] in [After Header] section. So by adding another one more table (attachment table) it will make APEX get confused. Anyway, I have tried it. It does not work.

The attachment will be save into my own table within the Oracle database.

Next step is to save the file attachment to be save in my own attachment table. Lets name my table as ATTACHMENT_FILES. 
CREATE TABLE ATTACHMENT_FILES
(
  ID                 NUMBER,
  BLOB_CONTENT       BLOB,
  MIMETYPE           VARCHAR2(255 BYTE),
  FILENAME           VARCHAR2(255 BYTE),
  LAST_UPDATE        DATE,
  CHARSET            VARCHAR2(128 BYTE),
  UPLOADED_BY        VARCHAR2(10 BYTE),
  DOC_SIZE           NUMBER
)
Since I already have my table ready, I will now need to create one process to copy the file from WWV_FLOW_FILES into ATTACHMENT_FILES.

This process must be create at point [Processing > Processes] on [Page Processing]
  1. Right click on [Processes] > Create
  2. Select [PL/SQL] and Next
  3. Give a name to identify the procesess and click Next (lets name it as 'CopyFile')
  4. On the [Enter PL/SQL Page Process], paste below code;
begin
insert into ATTACHMENT_FILES( id, blob_content, mimetype, filename, last_update, doc_size )
select :P1_YOUR_ID, blob_content, mime_type, filename, created_on, doc_size from  wwv_flow_files where  name = :P1_ATTACHMENT;
delete from wwv_flow_files where name = :P1_ATTACHMENT;
end;
So by now, you got the idea already right? First, we let the attachment to be saved into WWV_FLOW_FILES. Then we copied it over to our own table and delete the original data from WWV_FLOW_FILES to avoid consume space and storage.

To avoid any complex coding in PL/SQL, I believe this method is faster. It depends on your needs.

Hurmm..I will talk about sending email as Part 2 later on.

Update : This is the Part 2.

APEX : ORA-01008: not all variables bound

It is really frustrating if everything run not as per plan right?..:-)

Today I encounter error ORA-01008: not all variables bound, when executing a report from a SQL script. At first, I suspected because of a LEFT JOIN syntax problem.

What Oracle say about ORA-01008?
ORA-01008: not all variables bound
Cause: A SQL statement containing substitution variables was executed without all variables bound. All substitution variables must have a substituted value before the SQL statement is executed.
Action: In OCI, use an OBIND or OBINDN call to substitute the required values.

I not really understand it much. But below solution works well for me on my APEX application. And the report generation have no problem any more.

Initially, my SQL code was as below:

where employee = :P1_EMPLOYEE

Solution: 

where employee = v('P1_EMPLOYEE')

Have a good day!


Error on APEX : ORA-20001: Unable to bind..

ORA-20001: Unable to bind :P1005_YOUR_PAGE_ITEM_NAME verify length of item is 30 bytes or less. Use v() syntax to reference items longer than 30 bytes. ORA-01006: bind variable does not exist


I encountered an error as above when testing my application on APEX. So, normally I will googling around to find the solution. But unfortunately, I do not found a solid solution to my problem, particularly on the above error.

So I try to solve the error myself. After took couple of hours play around with it, finally it is resolved.


Important thing to take note are:

  • This error is not come from the database. It is from application itself.
  • No need to check your database table and re-define your table structure. Such as change to data length to 30 bytes etc.

Solution:

The problem is due to the naming of the page item. So in APEX, it must not more than 30 bytes. So, I rename my page item to something more lesser in character. It works for me. I hope it is work for you too.


Change your character of P1005_YOUR_PAGE_ITEM_NAME to something lesser!







ShareThis