SQL VBA查询将仅在小数据集上返回结果

时间:2018-07-09 19:10:15

标签: sql sql-server excel vba excel-vba

我正在构建一个宏,该宏将为我的团队自动执行报告。第一部分设置为根据在对话框中选择的唯一标识符查询SQL(使用MS SQL Server Management Studio),然后将这些结果输入步骤2。

构建宏时,我注意到当唯一标识符列表小于9,000时,查询返回的结果与预期的一样。但是,如果我尝试查询超过9000行的任何内容,该宏将无错误运行,但它不会返回结果,而是仅显示最后一个活动窗口。基本上看起来宏没有执行任何操作。

由于宏可以很好地与小型数据集一起使用,并且没有错误,因此我对如何使其在大型数据集上工作感到有些困惑。我们的报告通常超过10,000行。可以作为我的参考吗?任何见识将不胜感激。请让我知道是否需要其他见解。

编辑:

当前代码低于

Sub FilterLov1()
    Dim rng As Range
    Dim workrng As Range
    Dim workrng1 As String
    Dim today As String
    Dim lastRow As Long
    Dim dept As String
    Dim class As String
    Dim subclass As String
    Dim sSQL As String
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim wsname As String

    wsname = ActiveSheet.Name

    'Set omsid list for SQL query
    On Error GoTo Handler
    Set workrng = Application.InputBox("Range:", Type:=8)
    Application.ScreenUpdating = False

    'Set rng = ActiveSheet.Range(workrng)

    Dim mystring As String
    mystring = RangeToString(workrng)

    'Declare the SQL code here

    Set cn = New ADODB.Connection
    cn.Open "Provider=SQLOLEDB;Data Source=WAPRCN026A;Initial Catalog= STEP_MVIEWS;Integrated Security=SSPI"

    sSQL = "select NAME, GuidID, DATASTANDARDS_PATH, PRODUCT_NAME_120, MARKETING_COPY, BULLET01, BULLET02, BULLET03, BULLET04, BULLET05, BULLET06, WORKFLOWSTATE, CHANNELSTATUS, THDONLINESTATUS from STEP_MVIEWS.dbo.[OMSID TO DATASTANDARDS] inner join STEP_MVIEWS.dbo.SCORECARD10_APPROVED on name = OMSID where [omsid] in (" & mystring & ")"

    Set rs = New ADODB.Recordset
    rs.Open sSQL, cn

        'Sheets.Add After:=ActiveSheet

    Worksheets.Add.Name = "FiltersLOVRaw"
    Worksheets("FiltersLOVRaw").Cells(1, 1).CopyFromRecordset rs

    rs.Close
    Set rs = Nothing
    cn.Close
    Set cn = Nothing

    Cells.Select


    'Add Column Headers here for export file
    Sheets("FiltersLOVRaw").Select
    Rows("1:1").Select
    Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
    Cells(1, 1).value = "OMSID"
    Cells(1, 2).value = "PARENT LEAF GUID"
    Cells(1, 3).value = "FILE PATH"
    Cells(1, 4).value = "PRODUCT NAME (120)"
    Cells(1, 5).value = "MARKETING COPY (1500)"
    Cells(1, 6).value = "BULLET 01"
    Cells(1, 7).value = "BULLET 02"
    Cells(1, 8).value = "BULLET 03"
    Cells(1, 9).value = "BULLET 04"
    Cells(1, 10).value = "BULLET 05"
    Cells(1, 11).value = "BULLET 06"
    Cells(1, 12).value = "WORKFLOW STATUS"
    Cells(1, 13).value = "CHANNEL STATUS"
    Cells(1, 14).value = "THD ONLINE STATUS"

    Cells.Select


    With ActiveSheet
        lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
    End With

    'Sheets.Add
    'ActiveSheet.Name = "Export"

    'Rows(x - 1).EntireRow.Delete
    'Cells.Select
        Range("A1").Select

Handler:
    Exit Sub
End Sub
Function RangeToString(ByVal MyRange As Range) As String
    RangeToString = ""
    If Not MyRange Is Nothing Then
        Dim myCell As Range
        For Each myCell In MyRange
            RangeToString = RangeToString & ",'" & myCell.value & "'"
        Next myCell
        'Remove extra comma
        RangeToString = Right(RangeToString, Len(RangeToString) - 1)
        'RangeToString = Left(RangeToString, Len(RangeToString) - 1)
    End If
End Function

2 个答案:

答案 0 :(得分:0)

我知道在Oracle中,使用import os import subprocess os.chdir(r'filepath') subprocess.check_call([r"filepath\your_.exe_app", 'your_input']) 子句的值限制为1,000。

根据this post,有一个限制(在SQL Server中),成千上万。建议将ID列表加载到表中,然后对表进行查询。

答案 1 :(得分:0)

在IN子句中明确地在括号内包含大量值(用逗号分隔的数千个值),会消耗资源并返回错误8623或8632。

错误8623:

The query processor ran out of internal resources and could not produce a query plan. This is a rare event and only expected for extremely complex queries or queries that reference a very large number of tables or partitions. Please simplify the query. If you believe you have received this message in error, contact Customer Support Services for more information.

错误8632:

Internal error: An expression services limit has been reached. Please look for potentially complex expressions in your query, and try to simplify them.

要变通解决此问题,将项目存储在表的IN列表中,并在IN子句中使用SELECT子查询。

引用Microsoft docs


可以在SQL Server Management Studio中运行的示例
(或者,如果您没有(免费的)SSMS版本,则直接从Excel对数据库进行查询。)
如果要保留表格,请注释掉DROP语句。

--Sample SQL https://stackoverflow.com/questions/51252536/sql-vba-query-will-only-return-results-on-small-dataset/
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = N'CC') 
BEGIN
-- Create a new schema name so it does not interfere with existing tables
EXEC sys.sp_executesql N'CREATE SCHEMA [CC] AUTHORIZATION [dbo]'

-- Create the table that holds the values which your user chooses
CREATE TABLE [CC].[KeyList]([RowKeysYouWant] [int] NOT NULL) ON [PRIMARY]
ALTER AUTHORIZATION ON [CC].[KeyList] TO  SCHEMA OWNER

-- This is the existing table which has your data in it
CREATE TABLE [CC].[TableWithData]([pk] [int] NOT NULL,
    [data1] [char](2) NULL,[data2] [char](2) NULL) ON [PRIMARY]
ALTER AUTHORIZATION ON [CC].[TableWithData] TO  SCHEMA OWNER 

-- here are the rows that you want (put list of chosen items in here)
INSERT [CC].[KeyList] ([RowKeysYouWant]) VALUES (1),(2),(3),(5),(7)
-- this is your data table (fields data1 and data2 become null by default)
INSERT [CC].[TableWithData] ([pk]) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9)

-- This is the select you use to grab all the records in table KeyList
SELECT * FROM CC.TableWithData WHERE pk IN (SELECT RowKeysYouWant FROM CC.KeyList)

DROP TABLE [CC].[TableWithData]; DROP TABLE [CC].[KeyList]; DROP SCHEMA [CC]
END
GO

您将需要权限来创建模式和创建表以运行它。
如果您没有这些权限,只需在家用PC上安装SQL Server Express版本的副本并在其中运行脚本即可。
首先使您的SQL工作,然后担心如何使其在VBA中工作。 :-)