Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

Oracle returning a cursor from a function or procedure

BeefStuJul 21 2021

I have the following code, which appears to be working fine.

As you can in the last piece of SQL the date range is hard coded. Is there a way to wrap it in a procedure or function and return a cursor (passing the dates directly to the procedure or function ) then modifying my SQL to reference each day that falls between the date range.

Ie something like this without the hard coded dates

WITH calendar ( start_date, end_date ) AS (
SELECT DATE '2021-07-01', DATE '2021-07-30' FROM DUAL
UNION ALL
SELECT start_date + 1, end_date
FROM calendar
WHERE start_date + 1 <= end_date
)
SELECT start_date AS day
FROM calendar

CREATE OR REPLACE PROCEDURE generate\_dates  
 (  
  p\_start\_date  IN DATE,  
 p\_end\_date   IN DATE  
)  
AS   
    BEGIN  
    END;  
END generate\_dates;  

EXEC generate_dates(
DATE '2021-07-01',
DATE '2021-07-31');

ALTER SESSION SET
NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';

create table holidays(  
  holiday\_date DATE,  
 holiday\_name VARCHAR2(20)  
);  

INSERT into holidays  
  (holiday\_date,  
   holiday\_name)  
 VALUES  
(  
 TO\_DATE('2021/07/21 00:00:00',   'yyyy/mm/dd hh24:mi:ss'), 'July 21 2021');  

 
Create table employees(  
 employee\_id NUMBER(6),   
 first\_name VARCHAR2(20),  
 last\_name VARCHAR2(20),  
 card\_num VARCHAR2(10),  

work_days VARCHAR2(7)
);

 ALTER TABLE employees  
         ADD ( CONSTRAINT employees\_pk  
       PRIMARY KEY (employee\_id));  


INSERT INTO employees                     
(  
EMPLOYEE\_ID,  
first\_name,   
last\_name,  
card\_num,   
work\_days  

)
WITH names AS (
SELECT 1, 'Jane', 'Doe', 'F123456', 'NYYYYYN' FROM dual UNION ALL
SELECT 2, 'Madison', 'Smith', 'R33432','NYYYYYN'
FROM dual UNION ALL
SELECT 3, 'Justin', 'Case', 'C765341','NYYYYYN'
FROM dual UNION ALL
SELECT 4, 'Mike', 'Jones', 'D564311','NYYYYYN' FROM dual
) SELECT * FROM names;

create table timeoff(  
     seq\_num integer  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,  
employee\_id NUMBER(6),  
timeoff\_date DATE,  
timeoff\_type VARCHAR2(1),  
 constraint timeoff\_chk check (timeoff\_date=trunc(timeoff\_date, 'dd')),  
  constraint timeoff\_pk primary key (employee\_id, timeoff\_date)  
 );  

INSERT INTO timeoff (EMPLOYEE_ID,TIMEOFF_DATE,TIMEOFF_TYPE
)
WITH dts AS (
SELECT 1, to_date('20210726 00:00:00','YYYYMMDD HH24:MI:SS'),'V' FROM dual UNION ALL
SELECT 2, to_date('20210726 00:00:00','YYYYMMDD HH24:MI:SS'),'V' FROM dual UNION ALL
SELECT 2, to_date('20210727 00:00:00','YYYYMMDD HH24:MI:SS'),'V' FROM dual )
SELECT * FROM dts;

        CREATE TABLE  emp\_attendance(      
 seq\_num integer  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,  
  employee\_id NUMBER(6),  
  start\_date DATE,  
  end\_date DATE,  
  week\_number NUMBER(2),  
  create\_date DATE DEFAULT SYSDATE  
   );  

create table absences(  
seq\_num integer  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,  
employee\_id NUMBER(6),  
absent\_date DATE,  
constraint absence\_chk check (absent\_date=trunc(absent\_date, 'dd')),  
  constraint absence\_pk primary key (employee\_id, absent\_date)  
);  


INSERT INTO emp\_attendance (    EMPLOYEE\_ID, START\_DATE,END\_DATE,WEEK\_NUMBER)  
WITH dts AS (   
SELECT 1, to\_date('20210728 13:10:00','YYYYMMDD HH24:MI:SS'),  
to\_date('20210728 23:15:00','YYYYMMDD HH24:MI:SS'), 30  FROM dual UNION ALL   
SELECT 2, to\_date('20210728 12:10:10','YYYYMMDD HH24:MI:SS'),  
to\_date('20210728 20:15:01','YYYYMMDD HH24:MI:SS'), 30  FROM dual)  

SELECT * FROM dts;

SELECT e.employee_id,
c.day
FROM employees e
INNER JOIN (
WITH calendar ( start_date, end_date ) AS (
SELECT DATE '2021-07-01', DATE '2021-07-30' FROM DUAL
UNION ALL
SELECT start_date + 1, end_date
FROM calendar
WHERE start_date + 1 <= end_date
)
SELECT start_date AS day
FROM calendar
) c
PARTITION BY ( e.employee_id )
ON (SUBSTR(e.work_days, TRUNC(c.day) - TRUNC(c.day, 'IW') + 1, 1) = 'Y')
WHERE NOT EXISTS (
SELECT 1
FROM holidays h
WHERE c.day = h.holiday_date
)
AND NOT EXISTS(
SELECT 1
FROM timeoff t
WHERE e.employee_id = t.employee_id
AND t.timeoff_date = c.day
)
ORDER BY
e.employee_id,
c.day

Comments

mNem
Answer

Your table name contains invalid character.

Check for the permitted characters in the table name.

https://dev.mysql.com/doc/refman/5.7/en/identifiers.html

Invoke the below two statements on http://rextester.com/l/mysql_online_compiler  and check the results.

Create table if not exists 2015-SE-001 (id INTEGER not null primary key auto_increment, name varchar(30),  totalTheoryClasses INTEGER, totalLabs INTEGER, WeekNo INTEGER, DaysPresent INTEGER, DaysAbset INTEGER, Percentage FLOAT);

Create table if not exists 2015_SE_001 (id INTEGER not null primary key auto_increment, name varchar(30),  totalTheoryClasses INTEGER, totalLabs INTEGER, WeekNo INTEGER, DaysPresent INTEGER, DaysAbset INTEGER, Percentage FLOAT);

On the other hand, why would you need to create the tables on the fly?

Marked as Answer by Zulfi Khan · Sep 27 2020
unknown-7404

This means that I want to parameterize the table name.

That means you are doing SEVERAL things wrong.

1. You don't 'parameterize' table names in queries. The table name can NOT be a bind variable

2. You should NOT be using a parameter for the table name anyway. You should NOT be creating multiple identical tables with different names. That usually means you have the wrong data model.

This appears to be a continuation of your previous issue

How to check empty Excel cell using while loop?

Until you tell people ALL of the requirements about the real problem you are trying to solve it is hard to give you help.

Zulfi Khan

Hi,

Thanks for your suggestions. I have solved this prob:

2. You should NOT be using a parameter for the table name anyway. You should NOT be creating multiple identical tables with different names. That usually means you have the wrong data model.

Its easy. I am keeping each students' record in a separate table. And the Head can check it with a simple 'Select' query but now there is table name alteration he has to remember. I mean its simple to say "Select * from 2015_SE_21" as compared to using a where clause.

<On the other hand, why would you need to create the tables on the fly?>

I have to read excel sheet for roll numbers & then create tables for each rollNo & each table will contain attendance data for each specific student.

My code is:

import java.io.*;

import jxl.Sheet;

import jxl.Workbook;

import jxl.read.biff.BiffException;

import javax.swing.*;

import java.sql.*;

/**

*

* @author HP

*/

public class ReadExcelSheetMain6 {

private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; 

private static final String DB_URL = "jdbc:mysql://localhost/attendance";

   //  Database credentials

private static final String USER = "root";

private static final String PASS = "z";

private Connection conn = null;

private Statement stmt = null;

PreparedStatement pStmt = null;

    /**

     * @param args the command line arguments

     */

    public void readExcel() throws BiffException, IOException {

String FilePath = "D:\\Marks-2A-SE-OOP-2015.xls";

FileInputStream fs = new FileInputStream(FilePath);

Workbook wb = Workbook.getWorkbook(fs);

// TO get the access to the sheet

Sheet sh = wb.getSheet("Sheet1");

               

// To get the number of rows present in sheet

int totalNoOfRows = sh.getRows();

                JOptionPane.showMessageDialog(null, "KKK totalNoOfRows = " + totalNoOfRows);

// To get the number of columns present in sheet

int totalNoOfCols = sh.getColumns();

                JOptionPane.showMessageDialog(null, "GGG totalNoOfCols = " + totalNoOfCols);

                int row=8;

                int col=1;

                String rollNo=null;

                String newRollNo = null;

               

               

                //for ( row = 8; row < totalNoOfRows; row++) {

                   rollNo = sh.getCell(col, row).getContents();

                   newRollNo = rollNo.replace('-','_');

                   boolean isEmpty = rollNo == null || rollNo.trim().length() == 0;

                   //if (isEmpty)

                     // break;

                    try{

                          System.out.println("Comes Here1");

                           //STEP 2: Register JDBC driver

                           Class.forName("com.mysql.jdbc.Driver");

                           //STEP 3: Open a connection

                           System.out.println("Connecting to database...");

                           conn = DriverManager.getConnection(DB_URL,USER,PASS);

                           //STEP 4: Execute a query

                           System.out.println("Creating statement Testing 999 ..." + rollNo);

                           String sql;

                           sql = "Create table if not exists " + newRollNo+ " (id INTEGER not null primary key auto_increment, name varchar(30),  totalTheoryClasses INTEGER, totalLabs INTEGER, WeekNo INTEGER, DaysPresent INTEGER, DaysAbset INTEGER, Percentage FLOAT)";

                          

                           stmt = conn.createStatement();

                          

                          

                           //sql ="Create table if not exists Test(id Integer)";

                          

                            stmt.executeUpdate(sql);

                            System.out.println("Comes Here Testing 110");

                        }

                        catch(SQLException sqle) {

System.out.println("Error1 after modifying");

sqle.printStackTrace();

                       

                        }

                        catch(ClassNotFoundException cnfe) {

System.out.println("Error2");

                        }

                        catch (Exception e) {

System.out.println("Error3");

                        }

                        finally{

                           try{

                                 if(conn!= null)

                                 conn.close();

                               }

                       

                        catch(SQLException sqle) {

System.out.println("Error4");

                        }

                       }//finally

//                     }//for

                  

                   //System.out.println("rollNo" + rollNo);

                  

               

               

                //System.out.print(sh.getCell(col, row).getContents() + "\t");

/*for (int row = 0; row < totalNoOfRows; row++) {

for (int col = 0; col < totalNoOfCols; col++) {

System.out.print(sh.getCell(col, row).getContents() + "\t");

}

System.out.println();

}*/

    }

    public static void main(String[] args)throws BiffException, IOException {

        // TODO code application logic here

        ReadExcelSheetMain6 obj = new ReadExcelSheetMain6();

        obj.readExcel();

    }

   

}

I check the documentation under prepared statement but i cant find that prepared statement can not be allowed on create table query. Even stackoverflows provide its solutions. 

Problem Solved.Thanks.

Zulfi.

unknown-7404

I check the documentation under prepared statement but i cant find that prepared statement can not be allowed on create table query.

That is NOT what I said - reread my reply.

I said that table names can NOT be used for bind variables. You need to construct a query that has the table name already in it - you can't use a 'setXXX' statement to alter the table name.

I am keeping each students' record in a separate table.

That is what I meant when I said you are likely using the wrong data model.

You should keep like data in the same table. One table to hold rows for ALL students.

By using that correct data model your problem goes away - there is only ONE table name to remember and only one table to query.

mNem

Do a google search for "student attendance database" images. Should give you some idea.

Try to produce some queries with your design on paper first.

mNem

Try not to leave commented out code blocks in the methods. Keep it clean. It helps.

1 - 6

Post Details

Added on Jul 21 2021
16 comments
3,878 views