Need some SQL advice please
I am using a program called WinCC, in which I am using Vb script language with SQL.
I have a SQL table in which there are 3 columns, TagName, Value and Date
I need to display the Value for each TagName for each day in the chosen month.
The below SQL query give me same value for each day in the month. When I have different values for each day in the month.
Tags(0) = "Tag1"
Tags(1) = "Tag2"
TempTags(0) = "Temp1"
TempTags(1) = "Temp2"
ConnectionString = "Provider=SQL Native Client;Server=WIN81 \WINCC;Database=Teams;Trusted_Connection=yes"
Set Connection = CreateObject("ADODB.Connection")
Set rs = CreateObject ("ADODB.Recordset")
Connection.ConnectionString = ConnectionString
Connection.Open
For i = 0 To 2
SQLStr = "select Value FROM atrperformancestats WHERE TagName = '"+Tags(i)+"'And Month(Date)='"+date+"'"
rs = Connection.Execute(SQLStr)
HMIRuntime.Tags(TempTags(i)).Write rs("Value")
Next
I have tried changing my SQL query to get the value for each day in the user selected month but I am failing miserably...please help
Thank you so much
If the query returns multiple rows, you need a While loop to process the result set. Below is a parameterized example that assumes date is an integer representing the month.
Const adVarChar = 200
Const adInteger = 3
Const adParamInput = 1
Const adCmdText = 1
Tags(0) = "Tag1"
Tags(1) = "Tag2"
TempTags(0) = "Temp1"
TempTags(1) = "Temp2"
ConnectionString = "Provider=SQL Native Client;Server=WIN81 \WINCC;Database=Teams;Trusted_Connection=yes"
Set Connection = CreateObject("ADODB.Connection")
Set Command = CreateObject("ADODB.Command")
Connection.ConnectionString = ConnectionString
Connection.Open
Command.ActiveConnection = Connection
Command.CommandType = adCmdText
Command.CommandText = "SELECT Value FROM atrperformancestats WHERE TagName = ? And Month(Date) = ?;"
Set parmTagName = command.CreateParameter("TagName", adVarchar, adParamInput, 100)
Command.Parameters.Append(parmTagName)
Set parmDate = command.CreateParameter("Date", adInteger, adParamInput)
command.Parameters.Append(parmDate)
For i = 0 To 1
parmTagName.Value = Tags(i)
parmDate.Value = date
Set rs = Command.Execute()
While rs.EOF = False
HMIRuntime.Tags(TempTags(i)).Write rs("Value").Value
rs.MoveNext
WEnd
rs.Close
Next
In WinCC , a SCADA program which is not very code savy I eventually found a way...
j = 0
SQLStr = "Select Value FROM table1 WHERE Name = '" + Names(i) + "' And Month(Date) = '" + MonthSelect + "' order by date asc"
rs.Open SQLStr, Connection
Do Until j = 31
HMIRuntime.Tags(arrayInt(i)).Write rs("Value")
rs.MoveNext
i = i +1
j = j +1
Loop
And it works !!!
Thanks for all the help , your recommendation of a loop got me thinking
Related
I've written a VB Script to go through a folder, extract a record number from the filenames inside, query the corresponding zone for those record numbers, and rename/move the files as appropriate.
First I make a recordset of the files inside (rsFiles), and I build a SQL String from those record numbers as an inlist to query the corresponding zones into a second recordset (rsZones). Then I move through rsZones and write the appropriate zone back to rsFiles.
My code works with a small number of files (I've tested and gotten reliable results up to 200) but I need to process several thousand at a time... If I throw too many files at it, I get error 80040E14 "Could not find prepared statement with handle -1." at the line that does rsZones.MoveFirst.
I think this means rsZones doesn't have any records, but shouldn't that mean rsZones.EOF would resolve to TRUE? Also, I have the ADODB Command timeout set at 0, so why am I not getting records on a larger inlist?
Code extract below. Any help/ideas would be appreciate. Thanks!!
Const sSourceDir = "C:\MyDir\"
Set re = New RegExp
re.Global = False
Set rsFiles = CreateObject("ADOR.Recordset")
rsFiles.Fields.Append "File", adVarChar, MaxCharacters
rsFiles.Fields.Append "Record_Number", adVarChar, 10
rsFiles.Fields.Append "Zone", adVarChar, 2
rsFiles.Open
re.Pattern = "(\d{1,})_\d{1,}_[IPG]\S*.pdf"
Set oFolder = oFSO.GetFolder(sSourceDir)
Set oFiles = oFolder.Files
If oFiles.Count > 0 Then
For each oFile in oFiles
Set reMatches = re.Execute(oFile.Name)
If reMatches.Count > 0 Then
sRecordNumber = reMatches(0).subMatches(0)
sInlist = sInlist & "'" & sRecordNumber & "',"
Else
sRecordNumber = ""
End If
rsFiles.AddNew
rsFiles("File") = oFile.Name
rsFiles("Record_Number") = sRecordNumber
Next
End If
If sInlist = "" Then
MsgBox "No files matching record number pattern"
wScript.Quit
End If
sInlist = Left(sInlist, Len(sInlist)-1)
Const sConn = "Provider=SQLOLEDB;SERVER=my\server;DATABASE=default_database;TRUSTED_CONNECTION=yes"
sSQL = "select tablea.record_number, tablea.zone from tablea where tablea.record_number in (" & sInlist & ")"
Set oConn = CreateObject("ADODB.Connection")
oConn.ConnectionTimeout = 0
oConn.Open sConn
Set cmd = CreateObject("ADODB.Command")
With cmd
.ActiveConnection = oConn
.CommandText = sSQL
.CommandType = 1 'adCmdText
.CommandTimeout = 0
.Prepared = True
End With
set rsZones = CreateObject("ADODB.Recordset")
Set rsZones = cmd.Execute
If Not rsZones.EOF Then
rsZones.MoveFirst 'ERROR IS HERE
Do until rsZones.EOF
rsFiles.Filter = 0
rsFiles.Filter = "record_number = '" & rsZones(0) & "'"
rsFiles.MoveFirst
Do Until rsFiles.EOF
rsFiles("Zone") = rsZones("Zone")
rsFiles.MoveNext
Loop
rsZones.MoveNext
Loop
End If
rsZones.Close
How can I write an equivalent SQL script in T-SQL?
I've written this code in MS Access to edit records - how can I do the same thing in SQL Server?
For each combination of J_CaseNum and J_Index J_PersonIndex needs to be incremented. There can be anywhere from 1 to 50 person for a given combination.
Dim rs As Recordset
Dim rs1 As Recordset
Dim i As Long
Dim s As String
sql = "Select J_CaseNum, J_Index, J_VehicleIndex, J_PersonIndex, J_CaseNo, J_PersonID, Ind_Last_NM from dbo_DCIPS Order By J_CaseNum, J_Index, Ind_Last_NM"
Set rs = CurrentDb.OpenRecordset(sql)
Set rs1 = CurrentDb.OpenRecordset(sql)
rs.MoveLast
cnt = rs.RecordCount
rs.MoveFirst
i = 0
SysCmd acSysCmdInitMeter, "_", cnt
While Not rs.EOF
If i = 0 Then
rs.Edit
rs!J_PersonIndex = "01"
rs!J_CaseNo = rs!J_CaseNum & rs!J_Index
rs!J_PersonID = rs!J_CaseNo & rs!J_VehicleIndex & rs!J_PersonIndex
rs.Update
j = 1
i = 1
rs.MoveNext
Else
If (rs1!J_CaseNum = rs!J_CaseNum) And (rs1!J_Index = rs!J_Index) Then
j = j + 1
s = j
rs.Edit
rs!J_PersonIndex = Right("00" + s, 2)
rs!J_CaseNo = rs!J_CaseNum & rs!J_Index
rs!J_PersonID = rs!J_CaseNo & rs!J_VehicleIndex & rs!J_PersonIndex
rs.Update
rs.MoveNext
rs1.MoveNext
Else
j = 1
s = j
rs.Edit
rs!J_PersonIndex = Right("00" + s, 2)
rs!J_CaseNo = rs!J_CaseNum & rs!J_Index
rs!J_PersonID = rs!J_CaseNo & rs!J_VehicleIndex & rs!J_PersonIndex
rs.Update
rs.MoveNext
rs1.MoveNext
End If
End If
i = i + 1
SysCmd acSysCmdUpdateMeter, i
If (i Mod 1000) = 0 Then Stop
Wend
Thanks in advance
ok so you want a counter in each group of case/index/person. I would do something like this to get a unique person id.
SELECT ROW_NUMBER() OVER (partition BY caseNum,[index] order by [index])
AS personId , caseNum, [index], personName FROM table
And then you can use this dataset to insert into a new table or update existing table from this query (which is a modified command)
I have to write a program for my company's accountant, and I have a problem in returning articles' families in an array, all of the families I want to have have an Accounting code who begins with "707". Here's my code in VBScript :
Set objConnection = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\BASES\Base.mdb;Persist Security Info=False"
rs.CursorLocation = adUseClient
FamilleQuery = "Select Code from FamilleArticle Where CptVenteFrance Like '707%'"
rs.Open FamilleQuery, objConnection, adOpenStatic, adLockOptimistic
'rs.MoveFirst
'Do
'ListeFamille(rs.AbsolutePosition) = rs("Code")
'rs.MoveNext
'Loop until rs.EOF
'ListeFamilleString = rs.GetString(AdClipString, -1,"/","/"," ")
'ListeFamille = split(ListeFamilleString,"/")
'Set ListeFamille = rs.GetRows
'for i=0 to ubound(rs)
'ListeFamille(i) = rs.Fields("Code").Value(i)
'next
rs.Close
objConnection.Close
As comments you have all of my attempts to return the resultat of the recordset in an array and no one didn't work.
Can someone say where I'm wrong please ?
Give this a try
Option Explicit
'ADO Constants
Const adCmdText = 1
Const adParamInput = 1
Const adVarWChar = 202
'Would usually be passed in from somewhere
Dim value: value = "707%"
Dim cmd, rs, data
Dim conn: conn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\BASES\Base.mdb;Persist Security Info=False"
Dim sql: sql = "Select Code from FamilleArticle Where CptVenteFrance Like ?"
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandType = adCmdText
.CommandText = sql
Call .Parameters.Append(.CreateParameter("#value", adVarWChar, adParamInput, 50))
Set rs = .Execute(, Array(value))
If Not rs.EOF Then data = rs.GetRows()
Call rs.Close()
Set rs = Nothing
End With
Set cmd = Nothing
Dim row, rows
If IsArray(data) Then
'Test data (2d Array, 0 = column, 1 = row)
Call WScript.Echo(data(0, 0))
'Retrieving all rows
rows = UBound(data, 2)
For row = 0 To rows
'First column from each row.
Call WScript.Echo(data(0, row))
Next
Else
'No records returned
End If
Useful Links
Using Stored Procedure in Classical ASP .. execute and get results (talk about returning data as an Array you can traverse)
You don't need the Set in vbScript to set the array to the recordSet's rows. You only use a Set where setting an object reference, which isn't the case here.
ListeFamille = rs.GetRows will set ListeFamille to a 2 dimensional array with the results of the recordset in it.
Here's an excerpt from one of my own function libraries:
oConnection.open sConnectionString
oRecordSet.open sSql, oConnection
If oRecordSet.RecordCount = 0 Then
DataArray = ""
Else
oRecordSet.MoveFirst
DataArray = oRecordSet.GetRows
End If
I have a VBA script written to query HP ALM database using OTA API.
I want to query the database using a Recursive CTE. I don't know how to write that script within this VBA script.
VBA Script:::
Sub Extractor()
Const QCADDRESS = "http://alm/qcbin"
Const DOMAIN = "DOMAIN"
Const PROJECT = "PROJECT"
Const QCUSR = "user.name"
Const QCPWD = "123456"
Dim QCConnection, com, recset
Dim XLS, Wkb, Wks, i
Set QCConnection = CreateObject("TDApiOle80.TDConnection")
QCConnection.InitConnectionEx QCADDRESS
QCConnection.Login QCUSR, QCPWD
QCConnection.Connect DOMAIN, PROJECT
Set com = QCConnection.Command
com.CommandText = "Select * from ALL_LISTS"
Set recset = com.Execute
Set XLS = CreateObject("Excel.Application")
XLS.Visible = False
Set Wkb = XLS.Workbooks.Add
Set Wks = Wkb.Worksheets(1)
i = 1
Wks.Cells(i, 1).Value = "Data"
If recset.RecordCount > 0 Then
i = 2
recset.First
Do While Not (recset.EOR)
Wks.Cells(i, 1).Value = recset.FieldValue(0) 'fieldvalue(0) because the query extract only 1 field.
i = i + 1
recset.Next
Loop
Wkb.SaveAs "C:\myfile.xls"
End If
Wkb.Close
XLS.Quit
QCConnection.Disconnect
Set recset = Nothing
Set com = Nothing
Set QCConnection = Nothing
Set XLS = Nothing
Set Wkb = Nothing
Set Wks = Nothing
End Sub
CTE Query::::
with ReqCTE
as
(
SELECT
RQ_REQ_ID,
RQ_REQ_NAME,
RQ_FATHER_ID,
0 as lvl
FROM
td.REQ
where
RQ_REQ_ID = {?Father_ID}
union all
select
Folders.RQ_REQ_ID,
Folders.RQ_REQ_NAME,
Folders.RQ_FATHER_ID,
Child.lvl +1
from
ReqCTE as Child
join td.REQ as Folders on Folders.RQ_REQ_ID = Child.RQ_FATHER_ID
);
select * from ReqCTE;
Here is your code with your query embedded and your query variable declared as a VBA variable and referenced in the SQL script:
Sub Extractor()
Const QCADDRESS = "http://alm/qcbin"
Const DOMAIN = "DOMAIN"
Const PROJECT = "PROJECT"
Const QCUSR = "user.name"
Const QCPWD = "123456"
Dim par(0) As Variant
Dim QCConnection, com, recset
Dim XLS, Wkb, Wks, i
Set QCConnection = CreateObject("TDApiOle80.TDConnection")
QCConnection.InitConnectionEx QCADDRESS
QCConnection.Login QCUSR, QCPWD
QCConnection.Connect DOMAIN, PROJECT
Set com = QCConnection.Command
par(0) = 4 'set parameter value for Father_ID in SQL
com.CommandText = "with ReqCTE as (" & _
"SELECT RQ_REQ_ID, RQ_REQ_NAME, RQ_FATHER_ID, 0 as lvl FROM td.REQ " & _
"where RQ_REQ_ID = ? " & _
"Union all " & _
"select Folders.RQ_REQ_ID, Folders.RQ_REQ_NAME, Folders.RQ_FATHER_ID, Child.lvl +1 from ReqCTE as Child " & _
"join td.REQ as Folders on Folders.RQ_REQ_ID = Child.RQ_FATHER_ID); " & _
"select * from ReqCTE;"
Set recset = com.Execute(, par)
Set XLS = CreateObject("Excel.Application")
XLS.Visible = False
Set Wkb = XLS.Workbooks.Add
Set Wks = Wkb.Worksheets(1)
i = 1
Wks.Cells(i, 1).Value = "Data"
If recset.RecordCount > 0 Then
i = 2
recset.First
Do While Not (recset.EOR)
Wks.Cells(i, 1).Value = recset.FieldValue(0) 'fieldvalue(0) because the query extract only 1 field.
i = i + 1
recset.Next
Loop
Wkb.SaveAs "C:\myfile.xls"
End If
Wkb.Close
XLS.Quit
QCConnection.Disconnect
Set recset = Nothing
Set com = Nothing
Set QCConnection = Nothing
Set XLS = Nothing
Set Wkb = Nothing
Set Wks = Nothing
End Sub
UPDATED to avoid injection
I have a macro in Excel connecting to MS SQL, checking some counts and writing in my Excel sheet. It was working properly but it is not working now. I have an error code like this:
Run-time error -2147217871 Query Timeout Expired
My time out value is 960 but it showing me this problem.
How can I solve this problem?
I am sharing code with you:
Sub GetDataFromADO()
'Declare variables'
Set objMyConn = New ADODB.Connection
Set objMyCmd = New ADODB.Command
Set objMyRecordset = New ADODB.Recordset
'Open Connection'
objMyConn.ConnectionString = "Provider=SQLOLEDB;Data Source=<server>;User ID=<id>;Password=<pass>;"
'For Timeout'
Application.ODBCTimeout = 960
objMyConn.Open
'Set and Excecute SQL Command'
Set objMyCmd.ActiveConnection = objMyConn
'Set Recordset'
Set objMyRecordset.ActiveConnection = objMyConn
currentDate = Worksheets("RUN").Range("A1").Value
'-----------------------------------------------------------------------------------
cnt = 0
currentSheet = "LegalInsCrawling" 'Seq
cell = Worksheets(currentSheet).Range("A1").Value
Do
cnt = cnt + 1
cell = Worksheets(currentSheet).Range("A1").Offset(cnt).Value
Loop Until cell = "" Or cell = CDate(currentDate)
Worksheets(currentSheet).Range("A1").Offset(cnt).Value = currentDate
objMyCmd.CommandText = "<mssql query>"
objMyCmd.Execute
'Open Recordset'
objMyRecordset.Open objMyCmd
Worksheets(currentSheet).Range("B1").Offset(cnt).CopyFromRecordset (objMyRecordset)
objMyRecordset.Close
'------
cnt = 0
currentSheet = "LegalInsCrawling" 'HomePageCrawlingCount
cell = Worksheets(currentSheet).Range("A1").Value
Do
cnt = cnt + 1
cell = Worksheets(currentSheet).Range("A1").Offset(cnt).Value
Loop Until cell = "" Or cell = CDate(currentDate)
Worksheets(currentSheet).Range("A1").Offset(cnt).Value = currentDate
objMyCmd.CommandText = "<mssql query>"
objMyCmd.Execute
'Open Recordset'
objMyRecordset.Open objMyCmd
Worksheets(currentSheet).Range("D1").Offset(cnt).CopyFromRecordset (objMyRecordset)
objMyRecordset.Close