Operation is not allowed when the object is closed (Object is not closed) - vbscript

The following code, is generating that error.
Set getList = Server.CreateObject("ADODB.Command")
getList.ActiveConnection=EV_WikiConn
getList.Prepared = true
getList.commandtext= "declare #Lookup table(Id int identity(1, 1) , SongTitle nvarchar(512) )
insert into #Lookup(SongTitle)select * from ( values ('Deuce')) as x(a)
select A.AlbumName, S.SongTitle , S.Writers , S.Vocals , S.SID , S.TheTime
from Albums A inner join Songs S on A.AID = S.AID inner join #Lookup L on L.SongTitle = S.SongTitle order by L.Id"
set rsList = getList.execute
while not rsList.eof ' Error is on this line here.
I added this code here
Set getList = Server.CreateObject("ADODB.Command")
getList.ActiveConnection=EV_WikiConn
getList.Prepared = true
getList.commandtext= "declare #Lookup table(Id int identity(1, 1) , SongTitle nvarchar(512) )
insert into #Lookup(SongTitle)select * from ( values ('Deuce'),('Strutter'),('Parasite')) as x(a)
select A.AlbumName, S.SongTitle , S.Writers , S.Vocals , S.SID , S.TheTime
from Albums A inner join Songs S on A.AID = S.AID inner join #Lookup L on L.SongTitle = S.SongTitle order by L.Id"
set rsList = getList.execute
If rsList.State <> adStateOpen Then
While rsList.State <> adStateOpen
Set rsList = rsList.NextRecordset
rsList.movenext
wend
end if
This makes it run, however, I only get one record, instead of the 10 that is in the actual form. So, this is not going to work, but wanted to show what I have tried so far.

OK, got it all figured out. below is the code that was used, with a few notes in the code, to show what I did to make it work.
Set getList = Server.CreateObject("ADODB.Command")
getList.ActiveConnection=EV_WikiConn
getList.Prepared = true
getList.commandtext = _
"SET NOCOUNT ON " & _
"declare #Lookup table(Id int identity(1, 1) , " & _
"SongTitle nvarchar(512) ) " & _
"insert into #Lookup(SongTitle)select * from " & _
"( values ('Hotter_Than_Hell'), ('Firehouse'), ('She'), " & _
"('Parasite'), ('Nothin''_To_Lose')) as x(a) " & _
"select A.AlbumName, S.SongTitle , S.Writers , S.Vocals , " & _
"S.SID , S.TheTime from Albums A inner join " & _
"Songs S on A.AID = S.AID inner join " & _
"#Lookup L on L.SongTitle = S.SongTitle order by L.Id"
' the SET NOCOUNT ON, was added, but did not resolve the issue, I just left it in.
' The next 3 lines is what fixed the issue.
While rsList.State <> adStateOpen
Set rsList = rsList.NextRecordset
Wend
While Not rsList.EOF%>
<%=rsList("SongTitle")%>
<%rsList.movenext
wend
rsList.Close
set rsList = nothing

Regardless of what the OP believes this is a duplicate of
ADODB.Recordset error '800a0e78' Operation is not allowed when the object is closed
If we analyse the original code revision (ignoring the hard wrap which will cause an error in VBScript)
Set getList = Server.CreateObject("ADODB.Command")
getList.ActiveConnection=EV_WikiConn
getList.Prepared = true
getList.commandtext= "declare #Lookup table(Id int identity(1, 1) , SongTitle nvarchar(512) )
insert into #Lookup(SongTitle)select * from ( values ('Deuce')) as x(a)
select A.AlbumName, S.SongTitle , S.Writers , S.Vocals , S.SID , S.TheTime
from Albums A inner join Songs S on A.AID = S.AID inner join #Lookup L on L.SongTitle = S.SongTitle order by L.Id"
set rsList = getList.execute
while not rsList.eof ' Error is on this line here.
You can see that the original issue is the lack of
SET NOCOUNT ON;
to stop the closed ADODB.Recordset object being returned for the initial INSERT operation.
The subsequent edits the OP makes confuses the issue, before this adding SET NOCOUNT ON; would have fix the problem without needing further changes.
The next revision is where the confusion begins (again, ignoring the hard wrap which will cause an error in VBScript)
Set getList = Server.CreateObject("ADODB.Command")
getList.ActiveConnection=EV_WikiConn
getList.Prepared = true
getList.commandtext= "declare #Lookup table(Id int identity(1, 1) , SongTitle nvarchar(512) )
insert into #Lookup(SongTitle)select * from ( values ('Deuce'),('Strutter'),('Parasite')) as x(a)
select A.AlbumName, S.SongTitle , S.Writers , S.Vocals , S.SID , S.TheTime
from Albums A inner join Songs S on A.AID = S.AID inner join #Lookup L on L.SongTitle = S.SongTitle order by L.Id"
set rsList = getList.execute
If rsList.State <> adStateOpen Then
While rsList.State <> adStateOpen
Set rsList = rsList.NextRecordset
rsList.movenext
wend
end if
Let's just dissect this part
If rsList.State <> adStateOpen Then
While rsList.State <> adStateOpen
Set rsList = rsList.NextRecordset
rsList.movenext
wend
end if
First the If and While loop do the same thing accept the While does it repeatedly until the condition is met, making the If completely irrelevant.
The While loop checks for the current state of the ADODB.Recordset which without SET NOCOUNT ON; is returned as adStateClosed (due to the INSERT operation). This is fine but by changing the While loop from
while not rsList.eof
to
While rsList.State <> adStateOpen
the condition has been changed and the While is no longer checking for rsList.EOF which would be the case when we are enumerating the ADODB.Recordset object. However, now it is only checking for the .State of rsList which once .NextRecordset is called will exit the loop as a open ADODB.Recordset object has been returned. Because the condition has been met the loop will only run once calling .MoveNext once and only returning one record.
So to summaries using
SET NOCOUNT ON;
initially would have negated this whole scenario but hey "I don't understand the code" apparently.

Related

VBA to Oracle PLSQL returns no results

I have a macro in excel 2013 that is trying to connect to an Oracle database through "Microsoft ODBC for Oracle", the 32bit version, as the 64bit has issues for some reason. And though the query works from Toad, it returns no results in my macro.
I have tried shorter queries and they do return results making me think that this monster query cannot be appended correctly, but I have no way to test this.
My current situation is a giant and very ugly append to get this query into one long string to be executed by my ADOConnection.
SQLString = "SELECT LEVEL, "
SQLString = SQLString & "MSIL.SEGMENT1 ITEM, "
SQLString = SQLString & "MSIL.DESCRIPTION DESC_COMPONENT, "
SQLString = SQLString & "BIC.ITEM_TYPE, "
SQLString = SQLString & "BIC.SUPPLY_TYPE, "
SQLString = SQLString & "MSIL.PRIMARY_UOM_CODE UOM, "
SQLString = SQLString & "BIC.COMPONENT_QUANTITY, "
SQLString = SQLString & "item_attribute.ITEM_LENGTH, "
SQLString = SQLString & "item_attribute.ANGLE_LEFT, "
SQLString = SQLString & "item_attribute.ANGLE_RIGHT, "
SQLString = SQLString & "item_attribute.WT_HT_FLAG, "
SQLString = SQLString & "item_attribute.FABRICATION_NUMBER, "
SQLString = SQLString & "item_attribute.PANEL_WIDTH, "
SQLString = SQLString & "item_attribute.PANEL_HEIGHT, item_attribute.GLASS_DIM1, item_attribute.GLASS_DIM2, item_attribute.DIMENSION1, item_attribute.DIMENSION2, "
SQLString = SQLString & "item_attribute.DIMENSION3, item_attribute.DIMENSION4, item_Attribute.DIMENSION5 "
SQLString = SQLString & "FROM APPS.MTL_SYSTEM_ITEMS MSI, APPS.BOM_BILL_OF_MATERIALS BOM, APPS.BOM_INVENTORY_COMPONENTS_V BIC, APPS.MTL_SYSTEM_ITEMS MSIL, APPS.mtl_parameters mp, "
SQLString = SQLString & "APPS.MTL_ITEM_CATALOG_GROUPS_VL micg, (SELECT * FROM (SELECT msi.inventory_item_id, mde.element_name, "
SQLString = SQLString & "mdev.element_value "
SQLString = SQLString & "FROM APPS.mtl_parameters mp, APPS.mtl_system_items_b msi, APPS.MTL_ITEM_CATALOG_GROUPS_VL micg, APPS.MTL_DESCRIPTIVE_ELEMENTS mde, APPS.MTL_DESCR_ELEMENT_VALUES mdev "
SQLString = SQLString & "WHERE mp.organization_id = MSI.organization_id AND mp.organization_code = 'POR' "
SQLString = SQLString & "AND micg.ITEM_CATALOG_GROUP_ID = MSI.ITEM_CATALOG_GROUP_ID AND mde.ITEM_CATALOG_GROUP_ID = micg.ITEM_CATALOG_GROUP_ID "
SQLString = SQLString & "AND mdev.element_name = mde.element_name AND mdev.inventory_item_id = msi.inventory_item_id AND mde.element_name IN ('Length', "
SQLString = SQLString & "'Angle Left', 'Angle Right', 'Wt Ht Flag', 'Fabrication Number', 'Panel Width', 'Panel Height', 'Glass Dim 1', 'Glass Dim 2', "
SQLString = SQLString & "'Dimension 1', 'Dimension 2', 'Dimension 3', 'Dimension 4', 'Dimension 5')) PIVOT (MAX (Element_value) FOR (element_name) "
SQLString = SQLString & "IN ('Length' AS ITEM_LENGTH, 'Angle Left' AS ANGLE_LEFT, 'Angle Right' AS ANGLE_RIGHT, 'Wt Ht Flag' AS WT_HT_FLAG, "
SQLString = SQLString & "'Fabrication Number' AS FABRICATION_NUMBER, 'Panel Width' AS PANEL_WIDTH, 'Panel Height' AS PANEL_HEIGHT, 'Glass Dim 1' AS GLASS_DIM1, "
SQLString = SQLString & "'Glass Dim 2' AS GLASS_DIM2, 'Dimension 1' AS DIMENSION1, 'Dimension 2' AS DIMENSION2, 'Dimension 3' AS DIMENSION3, "
SQLString = SQLString & "'Dimension 4' AS DIMENSION4, 'Dimension 5' AS DIMENSION5)) ORDER BY inventory_item_id) Item_attribute WHERE 1 = 1 "
SQLString = SQLString & "AND item_Attribute.inventory_item_id(+) = msil.INVENTORY_ITEM_ID AND BOM.ASSEMBLY_ITEM_ID = MSI.INVENTORY_ITEM_ID "
SQLString = SQLString & "AND BOM.ORGANIZATION_ID = MSI.ORGANIZATION_id AND bom.bill_sequence_id = bic.bill_sequence_id AND NVL (bic.disable_date, SYSDATE) >= SYSDATE "
SQLString = SQLString & "AND BIC.component_ITEM_ID = MSIL.INVENTORY_ITEM_ID AND Bom.ORGANIZATION_ID = MSIL.ORGANIZATION_ID AND mp.organization_id = msi.organization_id "
SQLString = SQLString & "AND mp.organization_code = 'POR' "
SQLString = SQLString & "AND micg.ITEM_CATALOG_GROUP_ID = msi.ITEM_CATALOG_GROUP_ID AND MSI.ORGANIZATION_ID = (SELECT DISTINCT OOL.SHIP_FROM_ORG_ID "
'These two lines are the ones that have our variables
SQLString = SQLString & "FROM APPS.OE_ORDER_HEADERS_ALL OOH, APPS.OE_ORDER_LINES_ALL OOL, APPS.MTL_SYSTEM_ITEMS MSI1 WHERE OOH.ORDER_NUMBER = '" & OracleOrderNumber & "' "
SQLString = SQLString & "AND OOL.LINE_NUMBER = '" & OracleLineNumber & "' "
'----------------------------------------------------
SQLString = SQLString & "AND OOL.HEADER_ID = OOH.HEADER_ID AND MSI1.SEGMENT1 = OOL.ORDERED_ITEM AND MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID) "
SQLString = SQLString & "CONNECT BY PRIOR BIC.COMPONENT_ITEM_ID = BOM.ASSEMBLY_ITEM_ID START WITH MSI.INVENTORY_ITEM_ID IN (SELECT MSI1.INVENTORY_ITEM_ID "
SQLString = SQLString & "FROM APPS.OE_ORDER_HEADERS_ALL OOH, APPS.OE_ORDER_LINES_ALL OOL, APPS.MTL_SYSTEM_ITEMS MSI1 "
'These two lines are the ones that have our variables...again
SQLString = SQLString & "WHERE OOH.ORDER_NUMBER = '" & OracleOrderNumber & "' "
SQLString = SQLString & "AND OOL.LINE_NUMBER = '" & OracleLineNumber & "' "
'----------------------------------------------------
SQLString = SQLString & "AND OOL.HEADER_ID = OOH.HEADER_ID AND MSI1.SEGMENT1 = OOL.ORDERED_ITEM AND MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID)"
There original query in it's cleaned up form is here.
SELECT LEVEL,
MSIL.SEGMENT1 ITEM,
MSIL.DESCRIPTION DESC_COMPONENT,
BIC.ITEM_TYPE,
BIC.SUPPLY_TYPE,
MSIL.PRIMARY_UOM_CODE UOM,
BIC.COMPONENT_QUANTITY,
item_attribute.ITEM_LENGTH,
item_attribute.ANGLE_LEFT,
item_attribute.ANGLE_RIGHT,
item_attribute.WT_HT_FLAG,
item_attribute.FABRICATION_NUMBER,
item_attribute.PANEL_WIDTH,
item_attribute.PANEL_HEIGHT,
item_attribute.GLASS_DIM1,
item_attribute.GLASS_DIM2,
item_attribute.DIMENSION1,
item_attribute.DIMENSION2,
item_attribute.DIMENSION3,
item_attribute.DIMENSION4,
item_attribute.DIMENSION5
FROM APPS.MTL_SYSTEM_ITEMS MSI,
APPS.BOM_BILL_OF_MATERIALS BOM,
APPS.BOM_INVENTORY_COMPONENTS_V BIC,
APPS.MTL_SYSTEM_ITEMS MSIL,
APPS.mtl_parameters mp,
APPS.MTL_ITEM_CATALOG_GROUPS_VL micg,
( SELECT *
FROM (SELECT msi.inventory_item_id,
mde.element_name,
mdev.element_value
FROM APPS.mtl_parameters mp,
APPS.mtl_system_items_b msi,
APPS.MTL_ITEM_CATALOG_GROUPS_VL micg,
APPS.MTL_DESCRIPTIVE_ELEMENTS mde,
APPS.MTL_DESCR_ELEMENT_VALUES mdev
WHERE mp.organization_id = msi.organization_id
AND mp.organization_code = 'POR' -- Warehouse -- POR(Portland), ITM (Item Master), TAC (Tacoma), TEM (Temecula), CMP (Composites)
AND micg.ITEM_CATALOG_GROUP_ID =
msi.ITEM_CATALOG_GROUP_ID
AND mde.ITEM_CATALOG_GROUP_ID =
micg.ITEM_CATALOG_GROUP_ID
AND mdev.element_name = mde.element_name
AND mdev.inventory_item_id = msi.inventory_item_id
AND mde.element_name IN ('Length',
'Angle Left',
'Angle Right',
'Wt Ht Flag',
'Fabrication Number',
'Panel Width',
'Panel Height',
'Glass Dim 1',
'Glass Dim 2',
'Dimension 1',
'Dimension 2',
'Dimension 3',
'Dimension 4',
'Dimension 5'))
PIVOT
(MAX (Element_value)
FOR (element_name)
IN ('Length' AS ITEM_LENGTH,
'Angle Left' AS ANGLE_LEFT,
'Angle Right' AS ANGLE_RIGHT,
'Wt Ht Flag' AS WT_HT_FLAG,
'Fabrication Number' AS FABRICATION_NUMBER,
'Panel Width' AS PANEL_WIDTH,
'Panel Height' AS PANEL_HEIGHT,
'Glass Dim 1' AS GLASS_DIM1,
'Glass Dim 2' AS GLASS_DIM2,
'Dimension 1' AS DIMENSION1,
'Dimension 2' AS DIMENSION2,
'Dimension 3' AS DIMENSION3,
'Dimension 4' AS DIMENSION4,
'Dimension 5' AS DIMENSION5))
ORDER BY inventory_item_id) Item_attribute
WHERE 1 = 1
AND item_Attribute.inventory_item_id(+) = msil.INVENTORY_ITEM_ID
AND BOM.ASSEMBLY_ITEM_ID = MSI.INVENTORY_ITEM_ID
AND BOM.ORGANIZATION_ID = MSI.ORGANIZATION_id
AND bom.bill_sequence_id = bic.bill_sequence_id
AND NVL (bic.disable_date, SYSDATE) >= SYSDATE
AND BIC.component_ITEM_ID = MSIL.INVENTORY_ITEM_ID
AND Bom.ORGANIZATION_ID = MSIL.ORGANIZATION_ID
AND mp.organization_id = msi.organization_id
AND mp.organization_code = 'POR' -- Warehouse -- POR(Portland), ITM (Item Master), TAC (Tacoma), TEM (Temecula), CMP (Composites)
AND micg.ITEM_CATALOG_GROUP_ID = msi.ITEM_CATALOG_GROUP_ID
AND MSI.ORGANIZATION_ID =
(SELECT DISTINCT OOL.SHIP_FROM_ORG_ID
FROM APPS.OE_ORDER_HEADERS_ALL OOH,
APPS.OE_ORDER_LINES_ALL OOL,
APPS.MTL_SYSTEM_ITEMS MSI1
WHERE OOH.ORDER_NUMBER = '1483' --Oracle Sales Order Number
AND OOL.LINE_NUMBER = '1' -- Oracle Sales Order Line Number
AND OOL.HEADER_ID = OOH.HEADER_ID
AND MSI1.SEGMENT1 = OOL.ORDERED_ITEM
--AND OOL.ORDERED_ITEM LIKE '%*%'
AND MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID)
CONNECT BY PRIOR BIC.COMPONENT_ITEM_ID = BOM.ASSEMBLY_ITEM_ID
START WITH MSI.INVENTORY_ITEM_ID IN
(SELECT MSI1.INVENTORY_ITEM_ID
FROM APPS.OE_ORDER_HEADERS_ALL OOH,
APPS.OE_ORDER_LINES_ALL OOL,
APPS.MTL_SYSTEM_ITEMS MSI1
WHERE OOH.ORDER_NUMBER = '1483' --Oracle Sales Order Number
AND OOL.LINE_NUMBER = '1' -- Oracle Sales Order Line Number
AND OOL.HEADER_ID = OOH.HEADER_ID
AND MSI1.SEGMENT1 = OOL.ORDERED_ITEM
--AND OOL.ORDERED_ITEM like '%*%'
AND MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID)
And thoughts would be fantastic, I have tired multiple drivers and installs of Oracle, connection does not seem to be my issue, it is how the query is executed.
As asked for here is my connection code...
Private Const ConnectionString = "Driver={Microsoft ODBC for Oracle}; CONNECTSTRING=string; uid=APPSRO; pwd=APPSRO;"
' ADO Connection Global Variable - Declared here so that, once the connection is opened, it can be used by any part of the code'
Public ADOConn As Object
Private OracleOrder As ADODB.Recordset
Private Const AppName = "Oracle BOM Data"
Private Const Version = "v1.0.0"
Public Const BoxTitle = AppName & " " & Version
Public Function ADOOpen(ByRef ADOConn As Object) As Boolean
' Open the ADO connection to the database and link it to the Object we've been passed'
' Handle errors here'
On Error Resume Next
' Clear the Error table'
Err.Clear
' Create a new connection and link it to the Object passed in'
Set ADOConn = CreateObject("ADODB.Connection")
' Now open the ADO connection to the database'
ADOConn.Open ConnectionString
'ADOConn.Properties("PLSQLRSet") = True'
' Now check for errors. Err.Number will be zero if there's been no error' since we cleared the Error table
If Err.Number = 0 Then
' So if there's been no error, return true'
ADOOpen = True
Else
' Otherwise, return false'
ADOOpen = False
End If
End Function
Ok, here is the actual function using the connections we know work...
Public Function LoadOracleOrder(OracleOrderNumber As Double, OracleLineNumber As Double)
Dim SQLString As String
Dim TargetSheet As Worksheet
Dim TargetCell As Range
Dim SQLQuery As String
On Error Resume Next
SQLString = "MONSTROUS QUERY HERE"
Debug.Print SQLString
Set OracleOrder = ADOFetch(SQLQuery, ADOConn)
If Err.Number <> 0 Then
WarnMsgBox "Warning: Query failed." & Chr(10) & "Error No: " & Err.Number & Chr(10) & "Error Description: " & Err.Description, BoxTitle
Err.Clear
ElseIf OracleOrder.RecordCount = 0 Then
InfoMsgBox "Query Returned No Results.", BoxTitle
Else
Set TargetSheet = Nothing
Set TargetSheet = ThisWorkbook.Sheets("Oracle Order Data")
If TargetSheet Is Nothing Then
Set TargetSheet = ThisWorkbook.Sheets.Add
TargetSheet.Name = "Oracle Order Data"
End If
TargetSheet.Cells.ClearContents
TargetSheet.Range("A1") = "LEVEL"
TargetSheet.Range("B1") = "ITEM"
TargetSheet.Range("C1") = "DESC_COMPONENT"
TargetSheet.Range("D1") = "ITEM_TYPE"
TargetSheet.Range("E1") = "SUPPLY_TYPE"
TargetSheet.Range("F1") = "UOM"
TargetSheet.Range("G1") = "COMPONENT_QUANTITY"
TargetSheet.Range("H1") = "ITEM_LENGTH"
TargetSheet.Range("I1") = "ANGLE_LEFT"
TargetSheet.Range("J1") = "ANGLE_RIGHT"
TargetSheet.Range("K1") = "WT_HT_FLAG"
TargetSheet.Range("L1") = "FABRICATION_NUMBER"
TargetSheet.Range("M1") = "GLASS_DIM1"
TargetSheet.Range("N1") = "GLASS_DIM2"
TargetSheet.Range("O1") = "DIMENSION1"
TargetSheet.Range("P1") = "DIMENSION2"
TargetSheet.Range("Q1") = "DIMENSION3"
TargetSheet.Range("R1") = "DIMENSION4"
TargetSheet.Range("S1") = "DIMENSION5"
Set TargetCell = TargetSheet.Range("A2")
OracleOrder.MoveFirst
While Not OracleOrder.EOF
TargetCell.Value = OracleOrder.Fields(0).Value
TargetCell.Offset(0, 1).Value = OracleOrder.Fields(1).Value
TargetCell.Offset(0, 2).Value = OracleOrder.Fields(2).Value
TargetCell.Offset(0, 3).Value = OracleOrder.Fields(3).Value
TargetCell.Offset(0, 4).Value = OracleOrder.Fields(4).Value
TargetCell.Offset(0, 5).Value = OracleOrder.Fields(5).Value
TargetCell.Offset(0, 6).Value = OracleOrder.Fields(6).Value
TargetCell.Offset(0, 7).Value = OracleOrder.Fields(7).Value
TargetCell.Offset(0, 8).Value = OracleOrder.Fields(8).Value
TargetCell.Offset(0, 9).Value = OracleOrder.Fields(9).Value
TargetCell.Offset(0, 10).Value = OracleOrder.Fields(10).Value
TargetCell.Offset(0, 11).Value = OracleOrder.Fields(11).Value
TargetCell.Offset(0, 12).Value = OracleOrder.Fields(12).Value
TargetCell.Offset(0, 13).Value = OracleOrder.Fields(13).Value
TargetCell.Offset(0, 14).Value = OracleOrder.Fields(14).Value
TargetCell.Offset(0, 15).Value = OracleOrder.Fields(15).Value
TargetCell.Offset(0, 16).Value = OracleOrder.Fields(16).Value
TargetCell.Offset(0, 17).Value = OracleOrder.Fields(17).Value
TargetCell.Offset(0, 18).Value = OracleOrder.Fields(18).Value
TargetCell.Offset(0, 19).Value = OracleOrder.Fields(19).Value
Set TargetCell = TargetCell.Offset(1, 0)
OracleOrder.MoveNext
Wend
End If
On Error GoTo 0
End Function
ADO Fetch, as asked...
Public Function ADOFetch(SQLQuery As String, ByRef ADOConn As Object) As Object
' Takes an existing, open ADO connection and uses it to return a Recordset, Nothing if no data is returned, or False if there's an error
' Local Object for the Recordset
Dim ADORecSet As Object
' Handle errors internally
On Error Resume Next
' Clear the Error table
Err.Clear
' Set up the Recordset by executing the SQL query
Set ADORecSet = ADOConn.ExecuteSQL(SQLQuery)
' Now check for errors. Err.Number will be zero if there's been no error since we cleared the Error table
If Err.Number = 0 Then
' So if there's been no error, return the record set
Set ADOFetch = ADORecSet
End If
' And either way, clear our temporary Recordset
ADORecSet = Nothing
On Error GoTo 0
End Function
While I understand you resolved your syntax issue, I thought I might suggest two approaches for best practices moving forward:
EXPLICIT JOIN
Use the current ANSI-syntax in joining tables in your query. Right now, your SQL is using the older, deprecated implicit join (keys being used in WHERE clause) versus the current ANSI-standard with the explicit join (keys used in INNER JOIN...ON). While this makes no difference in the query optimizer in terms of performance (see SO post), using INNER JOIN tends to be more readable and maintainable especially if you have various WHERE conditions to manage. Below is an attempt to translate your query with the INNER JOIN clause. Please test before use (notice WHERE is more readable):
SELECT LEVEL,
MSIL.SEGMENT1 ITEM,
MSIL.DESCRIPTION DESC_COMPONENT,
BIC.ITEM_TYPE,
BIC.SUPPLY_TYPE,
MSIL.PRIMARY_UOM_CODE UOM,
BIC.COMPONENT_QUANTITY,
item_attribute.ITEM_LENGTH,
item_attribute.ANGLE_LEFT,
item_attribute.ANGLE_RIGHT,
item_attribute.WT_HT_FLAG,
item_attribute.FABRICATION_NUMBER,
item_attribute.PANEL_WIDTH,
item_attribute.PANEL_HEIGHT,
item_attribute.GLASS_DIM1,
item_attribute.GLASS_DIM2,
item_attribute.DIMENSION1,
item_attribute.DIMENSION2,
item_attribute.DIMENSION3,
item_attribute.DIMENSION4,
item_attribute.DIMENSION5
FROM APPS.MTL_SYSTEM_ITEMS MSI
INNER JOIN APPS.BOM_BILL_OF_MATERIALS BOM
INNER JOIN APPS.BOM_INVENTORY_COMPONENTS_V BIC
INNER JOIN APPS.MTL_SYSTEM_ITEMS MSIL
INNER JOIN APPS.mtl_parameters mp
INNER JOIN APPS.MTL_ITEM_CATALOG_GROUPS_VL micg
INNER JOIN
( SELECT *
FROM (SELECT msi.inventory_item_id,
mde.element_name,
mdev.element_value
FROM APPS.mtl_parameters mp,
INNER JOIN APPS.mtl_system_items_b msi
INNER JOIN APPS.MTL_ITEM_CATALOG_GROUPS_VL micg
INNER JOIN APPS.MTL_DESCRIPTIVE_ELEMENTS mde
INNER JOIN APPS.MTL_DESCR_ELEMENT_VALUES mdev
ON mp.organization_id = msi.organization_id AND
ON micg.ITEM_CATALOG_GROUP_ID = msi.ITEM_CATALOG_GROUP_ID AND
ON mde.ITEM_CATALOG_GROUP_ID = micg.ITEM_CATALOG_GROUP_ID AND
ON mdev.element_name = mde.element_name AND
ON mdev.inventory_item_id = msi.inventory_item_id
WHERE mp.organization_code = 'POR' -- Warehouse -- POR(Portland), ITM (Item Master), TAC (Tacoma), TEM (Temecula), CMP (Composites)
AND mde.element_name IN ('Length',
'Angle Left',
'Angle Right',
'Wt Ht Flag',
'Fabrication Number',
'Panel Width',
'Panel Height',
'Glass Dim 1',
'Glass Dim 2',
'Dimension 1',
'Dimension 2',
'Dimension 3',
'Dimension 4',
'Dimension 5'))
PIVOT
(MAX (Element_value)
FOR (element_name)
IN ('Length' AS ITEM_LENGTH,
'Angle Left' AS ANGLE_LEFT,
'Angle Right' AS ANGLE_RIGHT,
'Wt Ht Flag' AS WT_HT_FLAG,
'Fabrication Number' AS FABRICATION_NUMBER,
'Panel Width' AS PANEL_WIDTH,
'Panel Height' AS PANEL_HEIGHT,
'Glass Dim 1' AS GLASS_DIM1,
'Glass Dim 2' AS GLASS_DIM2,
'Dimension 1' AS DIMENSION1,
'Dimension 2' AS DIMENSION2,
'Dimension 3' AS DIMENSION3,
'Dimension 4' AS DIMENSION4,
'Dimension 5' AS DIMENSION5))
ORDER BY inventory_item_id) Item_attribute
ON item_Attribute.inventory_item_id(+) = msil.INVENTORY_ITEM_ID AND
ON BOM.ASSEMBLY_ITEM_ID = MSI.INVENTORY_ITEM_ID AND
ON BOM.ORGANIZATION_ID = MSI.ORGANIZATION_id AND
ON bom.bill_sequence_id = bic.bill_sequence_id AND
ON BIC.component_ITEM_ID = MSIL.INVENTORY_ITEM_ID AND
ON Bom.ORGANIZATION_ID = MSIL.ORGANIZATION_ID AND
ON mp.organization_id = msi.organization_id AND
ON micg.ITEM_CATALOG_GROUP_ID = msi.ITEM_CATALOG_GROUP_ID
WHERE 1 = 1
AND NVL (bic.disable_date, SYSDATE) >= SYSDATE
AND mp.organization_code = 'POR' -- Warehouse -- POR(Portland), ITM (Item Master), TAC (Tacoma), TEM (Temecula), CMP (Composites)
AND MSI.ORGANIZATION_ID =
(SELECT DISTINCT OOL.SHIP_FROM_ORG_ID
FROM APPS.OE_ORDER_HEADERS_ALL OOH
INNER JOIN APPS.OE_ORDER_LINES_ALL OOL
INNER JOIN APPS.MTL_SYSTEM_ITEMS MSI1
ON OOL.HEADER_ID = OOH.HEADER_ID AND
ON MSI1.SEGMENT1 = OOL.ORDERED_ITEM AND
ON MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID
WHERE OOH.ORDER_NUMBER = '1483' --Oracle Sales Order Number
AND OOL.LINE_NUMBER = '1' -- Oracle Sales Order Line Number
--AND OOL.ORDERED_ITEM LIKE '%*%'
)
CONNECT BY PRIOR BIC.COMPONENT_ITEM_ID = BOM.ASSEMBLY_ITEM_ID
START WITH MSI.INVENTORY_ITEM_ID IN
(SELECT MSI1.INVENTORY_ITEM_ID
FROM APPS.OE_ORDER_HEADERS_ALL OOH
INNER JOIN APPS.OE_ORDER_LINES_ALL OOL
INNER JOIN APPS.MTL_SYSTEM_ITEMS MSI1
ON OOL.HEADER_ID = OOH.HEADER_ID AND
ON MSI1.SEGMENT1 = OOL.ORDERED_ITEM AND
ON MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID
WHERE OOH.ORDER_NUMBER = '1483' --Oracle Sales Order Number
AND OOL.LINE_NUMBER = '1' -- Oracle Sales Order Line Number
--AND OOL.ORDERED_ITEM like '%*%'
)
EXTERNAL .SQL FILE
Because VBA does not allow strings across multiple lines without underscores and ampersands, consider avoiding the need for a long concatenation of the "giant" VBA string. Instead, read in an external .sql file into the VBA string.
This will allow effortless change of the SQL query as you only need to copy/paste from your database console into the .sql text file and your Excel macro will read in the latest version without worrying about adjusting commas, underscores, and ampersands. Save below script in a separate function and in your query function, LoadOracleOrder(), simply call it as: SQLString = ReadSQL():
Function ReadSQL() As String
On Error GoTo ErrHandle
Dim objFSO As Object, ofile As Object
Dim sqlFile As String, strSQL As String, dataLine As String
Dim readFile As Integer, i As Integer
Const ForReading = 1
' INITIALIZE OBJECTS
sqlFile = ActiveWorkbook.Path & "\OracleQuery.sql"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set ofile = objFSO.OpenTextFile(sqlFile, ForReading)
' OPEN FILE, READ LINES, CLOSE FILE
readFile = FreeFile()
Open sqlFile For Input As #readFile
strSQL = ""
Do While ofile.AtEndofStream <> True
strSQL = strSQL & ofile.ReadLine & vbNewLine
Loop
ReadSQL = strSQL
Close #readFile
ofile.Close
Set ofile = Nothing
Set objFSO = Nothing
Exit Function
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical
Set ofile = Nothing
Set objFSO = Nothing
Exit Function
End Function
Ok after running through issues that were overlooked due to my On Error Resume Next(thanks Tim), I found that I had a type mismatch, and I had a comma that should not have been in the sql (it had originally commented out but I must have changed it when appending the giant string).
Lastly, turns out there was a call to create a worksheet and then place the data in the project in which the macro was in (which is my personal file, not helpful.)
Thank you for your comments, and suggestions all of them helped me find the solution.

Error '80004005' only when SELECT DISTINCT with ASP Classic

I am developing in ASP VBScript at work and need to run a SELECT DISTINCT query but I am having some troubles.
I have other queries in my code that work perfectly fine, that do not use SELECT DISTINCT.
Here is what I am using:
Dim sections()
c = 1
set conn=Server.CreateObject("ADODB.Connection")
set rs=Server.CreateObject("ADODB.Recordset")
conn.Open "PROVIDER=Microsoft.Jet.OLEDB.4.0;Jet OLEDB:Database Password=******;User ID=Admin;" & _
"DATA SOURCE=" & Server.MapPath("modules.mdb")
rs.open "SELECT DISTINCT section FROM modules WHERE area='First' ORDER BY lvl ASC",conn
ReDim sections(10)
do while not rs.EOF
sections(c) = rs("section")
c = c + 1
rs.MoveNext
loop
rs.Close
conn.Close
set rs = nothing
set conn = nothing
Which gives me this error:
error '80004005'
on the line of the SQL query
The only way to fix this is to use "GROUP BY" instead of "DISTINCT"
SELECT DISTINCT section FROM modules WHERE area='First' ORDER BY lvl ASC
SELECT section FROM modules WHERE area='First' GROUP BY section ORDER BY lvl ASC

Update records details using Oracle 10g DB and VB.net

I am trying to figure out how to get some output as to what records were updated when running this query:
UPDATE CSR.TARGET ces
SET (STATUS_CODE, COMPLETE_DATE, DATA) =
(SELECT 'ERROR', '', REPLACE(c.Data, ' x</csr', '</csr')
FROM CSR.TARGET C
WHERE (c.EID = ces.EID)
AND c.STATUS_CODE = 'ERROR')
WHERE EXISTS (SELECT 1
FROM CSR.TARGET C
WHERE (c.EID = ces.EID)
AND c.STATUS_CODE = 'ERROR')
If there are 3 records that were updated by that above query then i would like to know what they were (record ID, etc). How would i go about doing that?
Currently it just tells me 3 records were updated and thats it. No other details.
Any help would be great! Thanks :o)
UPDATE
I am needing this for a query using VB.net so i do not think i can do PL/SQL type of thing?
Dim OracleCommand As New OracleCommand()
Dim ra As Integer
OracleCommand = New OracleCommand("UPDATE CSR.TARGET ces " & _
"SET (STATUS_CODE, COMPLETE_DATE, DATA) = " & _
"(SELECT 'ERROR', '', REPLACE(c.Data, ' x</csr', '</csr') " & _
"FROM CSR.TARGET C " & _
"WHERE (c.EID = ces.EID) " & _
"AND c.STATUS_CODE = 'ERROR') " & _
"WHERE EXISTS (SELECT 1 " & _
"FROM CSR.TARGET C " & _
"WHERE (c.EID = ces.EID) " & _
"AND c.STATUS_CODE = 'ERROR')", OracleConnection)
Try
ra = OracleCommand.ExecuteNonQuery()
OracleConnection.Close()
....
David
You should be able to use the RETURNING clause. Assuming that the EID column is the "record ID" you're referring to and that it is numeric
CREATE OR REPLACE TYPE num_tbl
IS
TABLE OF NUMBER;
DECLARE
l_modified_eids num_tbl;
BEGIN
UPDATE csr.target ces
SET <<omitted>>
WHERE <<omitted>>
RETURNING eid
BULK COLLECT INTO l_modified_eids;
<<Iterate through l_modified_eids to see which rows are modified>>
END;
Based on my reading of that query, all records that have an EID that matches the EID of a record who's status_code is 'ERROR' will be udpated. So if you have a table like this:
ID EID STATUS_CODE
-- --- -----------
1 1 ERROR
2 1 OKAY
3 2 OKAY
both records with ID 1 and 2 would be updated, because 2's EID field matches 1's EID field, and 1's EID field shows error. When it updates, it always uses the data from the row with the 'ERROR'.

VBA/ADODB Run-Time Error: 3704

The following VBA subroutine will run most queries just fine. (ie: SELECT * FROM DUAL)
Sub DisplayQuery(QueryString As String)
Dim rs As New ADODB.Recordset
Dim connStr As String
connStr = _
"Provider=MSDAORA.1;" _
& "User ID=abc;Password=123;" _
& "Data Source=xxx/xxx;"
out QueryString
rs.Open QueryString, connStr, adOpenStatic, adLockOptimistic
Range("DataTable").Clear
Cells(1, 1).CopyFromRecordset rs
End Sub
However, when I run the query below, the following error message immediately pops up: Run-time error '3704':Operation is not allowed when the object is closed.
with all_hours as
( select to_date('2009-11-03 05:00 PM','yyyy-mm-dd hh:mi PM') + numtodsinterval(level-1,'hour') hour
from dual
connect by level <= 4 /*hours*/
)
select h.hour
, count(case when h.hour = trunc(s.sampled_on,'hh24') then 1 end) sampled
, count(case when h.hour = trunc(s.received_on,'hh24') then 1 end) received
, count(case when h.hour = trunc(s.completed_on,'hh24') then 1 end) completed
, count(case when h.hour = trunc(s.authorized_on,'hh24') then 1 end) authorized
from all_hours h cross join sample s
group by h.hour
Why?
If I recall correctly, the ADO Command object has a default timeout (30 seconds, I think) which may be causing your problem: there should be a setting like
cn.ConnectionTimeout = (your value here)
which you could extend.
I just restructured my query (link), so that I could put it into a view. I then created a connection in Excel to view name.

linq where clause not in select statement

Can someone help me to convert from SQL Query to LINQ VB.NET:
select rls.* from Roles rls(nolock)
where rls.id not in (
select r.ID from usersRole ur (nolock)
inner join Roles r(nolock) on ur.RoleID = r.ID
where user_id = 'NY1772')
Thanks
i find my own answer...
'construct a where ID list
Dim lstRoleIDs = From ur In ctx.UsersRoles _
Join rl In ctx.Roles _
On ur.RoleID Equals rl.ID _
Where ur.User_ID = UserId _
Select rl.ID
Dim newQ = (From r In ctx.Roles _
Where Not lstRoleIDs.Contains( _
r.ID) _
Select New UserRoleList With {.ID = r.ID, .PermDesc = r.ID & " - " & r.Permission & " - " & r.PermissionDescription})
If you want to preserve the (NOLOCK) hints, I have blogged a handy solution using extension methods in C#. Note that this is the same as adding nolock hints to every table in the query.

Resources