1

I am stuck with this query. I try to convert but, i new at Oracle 11 g.

This is the ms sql stored procedure to convert with Oracle 11 g.

CREATE PROCEDURE [dbo].[GetCustomers_Pager]
       @SearchTerm VARCHAR(100) = ''
      ,@PageIndex INT = 1
      ,@PageSize INT = 10
      ,@RecordCount INT OUTPUT
AS
BEGIN
      SET NOCOUNT ON;
      SELECT ROW_NUMBER() OVER
      (
            ORDER BY [CustomerID] ASC
      )AS RowNumber
      ,[CustomerID]
      ,[CompanyName]
      ,[ContactName]
      ,[City]
      INTO #Results
      FROM [Customers]
      WHERE [ContactName] LIKE @SearchTerm + '%' OR @SearchTerm = ''
      SELECT @RecordCount = COUNT(*)
      FROM #Results

      SELECT * FROM #Results
      WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1

      DROP TABLE #Results
END

I find this ms sql stored procedure to this link

This is my fail oracle stored procedure. I'm stuck with INTO syntax.

CREATE OR REPLACE
PROCEDURE GetCustomers_Pager
( SearchTerm IN VARCHAR2
, PageIndex IN NUMBER DEFAULT 1
, PageSize IN NUMBER DEFAULT 10
, RecordCount OUT NUMBER
) AS
BEGIN  
  SELECT  
          ROW_NUMBER() OVER( ORDER BY CustomerID ASC )AS RowNumber,
          ,CustomerID
          ,CompanyName
          ,ContactName
          ,City
  INTO Results
  FROM Customers
  WHERE ( Customers LIKE SearchTerm + '%' OR ContactName LIKE SearchTerm + '%') OR SearchTerm = '';
  SELECT RecordCount = COUNT(*)
  FROM Results;
  SELECT * FROM Results
  WHERE RowNumber BETWEEN(PageIndex -1) * PageSize + 1 AND(((PageIndex -1) * PageSize + 1) + PageSize) - 1;
  DROP TABLE Results;

END GetCustomers_Pager;

Can anyone please help me?

oOZz
  • 657
  • 8
  • 18
  • What oracle version do you use? [perhaps this may help.](http://stackoverflow.com/questions/470542/how-do-i-limit-the-number-of-rows-returned-by-an-oracle-query-after-ordering) – Zohar Peled Apr 27 '15 at 06:58
  • 1
    First thing to do is to remove the `[..]` "quotes". Those are invalid for an SQL identifier. –  Apr 27 '15 at 07:04
  • 2
    I don't think the original SQLServer procedure makes any sense. It seems to be doing this: 1) Inserts a bunch of data from the `Customers` table that matches a contact name, into a temporary table `#Results`. 2) Fetches the row count of `#Results` into the `OUT` parameter `RecordCount`. 3) Executes a redundant query that mimicks pagination, against the `Results` table. The paginated result set is not used anywhere. 4) `DROP`s table `#Results`. Unless there is some hidden SQLServer magic going on, I think the same thing could be accomplished with a single `COUNT` against the `Customers` table. – Mick Mnemonic Apr 27 '15 at 11:09
  • First thing as per your pasted procedure you have 2 commas at SELECT ROW_NUMBER() OVER( ORDER BY CustomerID ASC )AS RowNumber, , and then into clause must have the same number of argument as in select statement – Pavan Bhatt Apr 27 '15 at 11:18
  • 1
    @MickMnemonic: There is indeed some "magic" going on, the procedure will (implicitely) return the result of the last select statement - that's why Oracle 12c introduced the "implicit result sets as well", but this is not available in 11g. I think the only option is to use a pipelined function that returns a result set and then select from that function. –  Apr 27 '15 at 11:28
  • @a_horse_with_no_name, wow that's really unintuitive (but nice to know)! Is the way it's used here an idiomatic usage example? Also, it feels awfully clumsy to implement pagination through a temp table and a stored procedure. Using a simple `SELECT` with an analytic windowing function like `row_number()` and an inline view (as presented by Tom Kyte [here](http://www.oracle.com/technetwork/issue-archive/2007/07-jan/o17asktom-093877.html)) is how I think it's best done in Oracle. I'd assume you can use almost the same syntax in the latest versions of SQLServer, as well. – Mick Mnemonic Apr 27 '15 at 14:40
  • @MickMnemonic: I'm not really a SQL Server guy, but I do see that all the time. It's one of the biggest obstacles and areas of confusion when people migrate from SQL Server to Oracle as far as I can tell. –  Apr 27 '15 at 14:44

2 Answers2

1

You can use only simple type variable in the SELECT INTO clause, for selecting into array use SELECT BULK COLLECT INTO. However you have to declare the variable you are selecting into and its type must match.

If you want to select the count only, use this:

SELECT COUNT(*) INTO RecordCount
FROM (SELECT ROW_NUMBER() OVER( ORDER BY CustomerID ASC )AS RowNumber,
             CustomerID,
             CompanyName,
             ContactName,
             City
     FROM Customers
     WHERE ( Customers LIKE SearchTerm + '%' OR ContactName LIKE SearchTerm + '%') OR SearchTerm = '') s
WHERE RowNumber BETWEEN (PageIndex-1)*PageSize + 1 AND PageIndex*PageSize;

If you want to return the records, you have to define the array type, add the output parameter Records and use SELECT * BULK COLLECT INTO Records and then RecordCount := Records.COUNT;.

But the preferred way to return data is a REF CURSOR output parameter, see http://oracle-base.com/articles/misc/using-ref-cursors-to-return-recordsets.php.

Pavel Gatnar
  • 3,987
  • 2
  • 19
  • 29
1

Oracle procedure code with cursor as output parameter:

CREATE OR REPLACE PROCEDURE GetCustomers_Pager (
  SearchTerm IN VARCHAR2, PageIndex IN NUMBER DEFAULT 1, PageSize IN NUMBER DEFAULT 10, 
  RecordCount OUT NUMBER, Records out sys_refcursor ) AS

begin
  -- count all matching rows
  select count(1) into RecordCount from Customers
    where ContactName like SearchTerm||'%';

  -- get all matching rows into cursor "Records"
  -- and filter them including PageIndex and PageSize parameters
  open Records for 
  select rn, customerid, companyName, contactName, City 
    from (
      select row_number() over (order by customerID) rn,
          customerid, companyName, contactName, City
        from customers where ContactName like SearchTerm||'%' )
    where rn between (PageIndex-1) * PageSize
      and (((PageIndex-1) * PageSize + 1) + PageSize) - 1;
end GetCustomers_Pager;

Example C# code calling this procedure and filling DataGridView:

OracleCommand cmd = new OracleCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "getcustomers_pager";
cmd.Connection = CONNECTION.oconn;
cmd.Parameters.Add(new OracleParameter("SearchTerm", OracleType.VarChar, 3)).Value = "Mar";
cmd.Parameters.Add(new OracleParameter("PageIndex", OracleType.Number)).Value = 1;
cmd.Parameters.Add(new OracleParameter("PageSize", OracleType.Number)).Value = 5;
OracleParameter p = new OracleParameter("RecordCount", OracleType.Number);
p.Direction = ParameterDirection.Output;
cmd.Parameters.Add(p);
p = new OracleParameter("Records", OracleType.Cursor);
p.Direction = ParameterDirection.Output;
cmd.Parameters.Add(p);

OracleDataAdapter da = new OracleDataAdapter();
da.SelectCommand = cmd;
DataSet ds = new DataSet();
da.Fill(ds);

dgv.DataSource = ds.Tables[0];
Ponder Stibbons
  • 14,723
  • 2
  • 21
  • 24
  • I create the oracle stored procedure but i'm using Ole DB dll. how can i use Oracle dll ? Any advice ? Tkanks... – oOZz Apr 27 '15 at 14:07
  • According to my knowledge you should just replace `OracleCommand` with `OracleDBCommand`, `OracleType` with `OracleDBType` etc., look what Intellisense suggest. Not sure of that, but this should work, just google for examples. – Ponder Stibbons Apr 27 '15 at 14:15
  • OracleType.Cursor does not support with Ole Db. Probably i can use oracle data access dll. Thanks for your help. – oOZz Apr 27 '15 at 14:22