after insert get primary key value in textbox - sql-server

I have 2 tables, TableA and TableB. IMAT_PRIORITY_ID is primary key in TableA.
How can I get the value of IMAT_PRIORITY_ID in a textbox after inserting into TableA?
strSQL1 = "INSERT TableA (IMAT_PRIORITY_ID,JOB_NO,BATCH_NO) VALUES (SQ_PRIOTITY_ID.nextval," & JOB_NO.Text & "','" & BATCH_NO.Text & "')"
With adoCommand
.ActiveConnection = adoconn
.CommandType = adCmdText
.CommandText = strSQL1
.Prepared = True
.Execute , , adCmdText + adExecuteNoRecords
End With
strSQL1 = "INSERT TableB (ISBN_SERIAL_NO,IMAT_PRIORITY_ID,ISBN) VALUES (ISBN_SERIAL_NO.NEXTVAL,'" & IMAT_PRIORITY_ID.Text & "','" & ISBN.Text & "')"
With adoCommand
.ActiveConnection = adoconn
.CommandType = adCmdText
.CommandText = strSQL1
.Prepared = True
.Execute , , adCmdText + adExecuteNoRecords
End With

To get the last identity (PRIMARY KEY) generated from the insert statement you can query it as follows..
strSQL1 = "INSERT TableA (IMAT_PRIORITY_ID,JOB_NO,BATCH_NO) VALUES (SQ_PRIOTITY_ID,JOB_NO,BATCH_NO) VALUES (SQ_PRIOTITY_ID.nextval," & JOB_NO.Text & "','" & BATCH_NO.Text & "');SELECT SCOPE_IDENTITY()"
You can find more details over here

Related

Dynamically Binding parameters to push to SQL Server

I have a lot of historical data I'm pushing to SQL. As a stop gap I'm coding this in VBA first. I open the .xlsx file, put the headers into an array to determine what SQL table the data goes into. Then I'm using solution #3 from INSERT INTO statement from Excel to SQL Server Table using VBA to base my SQL string on. I'm throwing an automation error at the .parameters.append line. Is there another way to dynamically append the parameters? Or is this just incorrect syntax? I appreciate any help!
Code:
'creates db connection
Set conn = CreateObject("ADODB.Connection")
With conn
.Provider = "Microsoft.ACE.OLEDB.12.0;"
.ConnectionString = "Data Source=" & wbk.FullName & ";" & "Excel 8.0;HDR=Yes;IMEX=0;Mode=ReadWrite;"
.Open
End With
sqlStr = "INSERT INTO DB_Name." & tblname & " ("
For i = 1 To UBound(hdrary)
If i <> UBound(hdrary) Then
sqlStr = sqlStr & hdrary(i, 1) & ", "
Else
sqlStr = sqlStr & hdrary(i, 1) & ") VALUES ("
End If
Next i
For i = 1 To UBound(hdrary)
If i <> UBound(hdrary) Then
sqlStr = sqlStr & "?, "
Else
sqlStr = sqlStr & "?)"
End If
Next i
'Statement follows this example:
'strSQL = "INSERT INTO " & Database_Name & ".[dbo]." & Table_Name & _
' " ([Audit], [Audit Type], [Claim Received Date], [Date Assigned], [Date Completed]," & _
' " [Analyst], [Customer], [ID], [Affiliate], [Facility], [DEA], [Acct Number], [Wholesaler]," & _
' " [Vendor], [Product], [NDC], [Ref], [Claimed Contract], [Claimed Contract Cost]," & _
' " [Contract Price Start Date], [Contract Price End Date], [Catalog Number], [Invoice Number], [Invoice Date]," & _
' " [Chargeback ID], [Contract Indicator], [Unit Cost],[WAC], [Potential Credit Due]," & _
' " [Qty], [Spend],[IP-DSH indicator Y/N], [DSH and/or HRSA Number], [Unique GPO Code]," & _
' " [Comment],[ResCode],[Correct Cost],[CRRB CM],[CRRB Rebill],[CRRB Date])" & _
' " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," _
' " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
lastrow = wks.Cells(Rows.count, "a").End(xlUp).Row
sys.Close
For i = 2 To lastrow
Set cmd = CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn ' CONNECTION OBJECT
.CommandText = sqlStr ' SQL STRING
.CommandType = adCmdText
' BINDING PARAMETERS
For j = 1 To UBound(hdrary)
.Parameters.Append .CreateParameter("s" & hdrary(j, 1), adVarChar, adParamInput, 255, wks.Cells(i, j))
.Execute
Next j
End With
Set cmd = Nothing
Next i
UPDATED: Based on #joel-coehoorn's answer, I updated the command and deleted the wbk.close. I'm throwing a "Item cannot be found in the collection corresponding to the requested name or ordinal." on the line cmd.Parameters(j).Value = wks.Cells(i, j).Value
'create command object
Set cmd = CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn ' CONNECTION OBJECT
.CommandText = sqlStr ' SQL STRING
.CommandType = adCmdText
End With
'pre-binds parameters
For j = 1 To UBound(hdrary)
Set k = cmd.CreateParameter(Chr(34) & hdrary(j, 1) & Chr(34), adVarChar, adParamInput, 255)
cmd.Parameters.Append k
Next j
'loops through mm worksheet by row
For i = 2 To lastrow
'SET PARAMETER VALUES
For j = 1 To UBound(hdrary)
cmd.Parameters(j).Value = wks.Cells(i, j).Value
Next j
'RUN THE SQL COMMAND
cmd.Execute
Next i
Set cmd = Nothing
My VBA is more than a little rusty, so there's likely a mistake in here, but I do believe this will get you to a better place.
That disclaimer out of the way, a . is just another binary operator, and so I think the space in
.Parameters.Append .CreateParameter
is not doing all the work you think it is, in that it's not equivalent to
cmd.Parameters.Append cmd.CreateParameter
but rather
cmd.Parameters.Append.CreateParameter
which of course is not a thing.
You probably need to do something like this instead:
Dim p
For j = 1 To UBound(hdrary)
Set p = .CreateParameter("s" & hdrary(j, 1), adVarChar, adParamInput, 255, wks.Cells(i, j))
.Parameters.Append p
Next j
.Execute
Note we don't call .Execute until we finish creating all the parameters.
Additionally, this code is itself inside a loop. You really don't need to recreate cmd or all those parameters again on every loop iteration. Rather, you should create the command and parameters once, and then only update the parameters' .Value properties inside the loop.
' ...
sys.Close
Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = conn ' CONNECTION OBJECT
cmd.CommandText = sqlStr ' SQL STRING
cmd.CommandType = adCmdText
' PRE-BINDING PARAMETERS
Dim p
For j = 1 To UBound(hdrary)
Set p = cmd.CreateParameter("s" & hdrary(j, 1), adVarChar, adParamInput, 255)
cmd.Parameters.Append p
Next j
' LOOP THROUGH EACH ROW
For i = 2 To lastrow
'SET PARAMETER VALUES
For j = 1 To UBound(hdrary)
cmd.Parameters(j-1).Value = wks.Cells(i, j)
Next j
'RUN THE SQL COMMAND
cmd.Execute
Next i
Set cmd = Nothing
Thanks to #Joel-Coehoorn here is the final code!
'creates db connection
Set conn = CreateObject("ADODB.Connection")
With conn
.Provider = "Microsoft.ACE.OLEDB.12.0;"
.ConnectionString = "Data Source=" & wbk.FullName & ";" & "Excel 8.0;HDR=Yes;IMEX=0;Mode=ReadWrite;"
.Open
End With
sqlStr = "INSERT INTO DB_Name." & tblname & " ("
'puts in columns
For i = 1 To UBound(hdrary)
If i <> UBound(hdrary) Then
sqlStr = sqlStr & hdrary(i, 1) & ", "
Else
sqlStr = sqlStr & hdrary(i, 1) & ") VALUES ("
End If
Next i
'placeholders for VALUES
For i = 1 To UBound(hdrary)
If i <> UBound(hdrary) Then
sqlStr = sqlStr & "?, "
Else
sqlStr = sqlStr & "?)"
End If
Next i
'Statement follows this example:
'strSQL = "INSERT INTO " & Database_Name & ".[dbo]." & Table_Name & _
' " ([Audit], [Audit Type], [Claim Received Date], [Date Assigned], [Date Completed]," & _
' " [Analyst], [Customer], [ID], [Affiliate], [Facility], [DEA], [Acct Number], [Wholesaler]," & _
' " [Vendor], [Product], [NDC], [Ref], [Claimed Contract], [Claimed Contract Cost]," & _
' " [Contract Price Start Date], [Contract Price End Date], [Catalog Number], [Invoice Number], [Invoice Date]," & _
' " [Chargeback ID], [Contract Indicator], [Unit Cost],[WAC], [Potential Credit Due]," & _
' " [Qty], [Spend],[IP-DSH indicator Y/N], [DSH and/or HRSA Number], [Unique GPO Code]," & _
' " [Comment],[ResCode],[Correct Cost],[CRRB CM],[CRRB Rebill],[CRRB Date])" & _
' " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," _
' " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
lastrow = wks.Cells(Rows.count, "a").End(xlUp).Row
Debug.Print sqlStr
sys.Close
'create command object
Set cmd = CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn ' CONNECTION OBJECT
.CommandText = sqlStr ' SQL STRING
.CommandType = adCmdText
End With
'pre-binds parameters
For j = 1 To UBound(hdrary)
Set k = cmd.CreateParameter(Chr(34) & hdrary(j, 1) & Chr(34), adVarChar, adParamInput, 255)
cmd.Parameters.Append k
Next j
'loops through worksheet by row
For i = 2 To lastrow
'sets parameter values and accounts for 0 based array
For j = 0 To cmd.Parameters.count - 1
cmd.Parameters(j).Value = wks.Cells(i, j + 1).Value
Next j
'RUN THE SQL COMMAND
cmd.Execute
Next i
Set cmd = Nothing

VB6 - How to execute multiple SQL queries in one call

I have an old slow procedure in VB6 using ADO to run many sql queries in many calls. Its taking too many hours. I want to test if sending all queries in one single query (most of them are just update or insert) to save network and calling time. How can I implement this, and also suggests if this would save time and boost performance?
qry = "Update table1 Set col1 = 'eerere' Where 1=1"
qry = qry & vbCrLf & " AND MyID = " & MyID & vbCrLf
ExecSQL qry, DBCon, adAsyncExecute
qry = "Insert Into TableMain"
qry = qry & "Select col1,col2,col3 from Table2 Where 1=1"
qry = qry & vbCrLf & " AND MyID = " & MyID & vbCrLf
ExecSQL qry, DBCon, adAsyncExecute
qry = "Update table5 Set col1 = 'eerere' Where 1=1"
qry = qry & vbCrLf & " AND MyID = " & MyID & vbCrLf
ExecSQL qry, DBCon, adAsyncExecute
You can combine them into one call by separating the commands with a semi-colon:
qry = "Update table1 Set col1 = 'eerere' Where 1=1"
qry = qry & vbCrLf & " AND MyID = " & MyID & "; " & vbCrLf
qry = qry & "Insert Into TableMain"
qry = qry & "Select col1,col2,col3 from Table2 Where 1=1"
qry = qry & vbCrLf & " AND MyID = " & MyID & "; " & vbCrLf
It will probably give you some small performance improvement, if it doesn't cause any errors.

I am gettin a null error in the code below for one user

The function below is trying to get the earliest date from a table with 3 dates, one for each type of user, care, sales and manager. This is to build up the diary system by first finding the first date in the diary dates. It's working for some users, but in one case the values do not return at and it gives null.
Private Function GetEarliestDate() As Date
Dim strSQL As String
Dim cmd As New SqlCommand
Dim dDate As Date
Try
strSQL = "Select dT.RecordID, MIN(dT.inDate) As [EarliestDate]
FROM (
Select RecordID, SentDate As [inDate]
From tblOrderDetails Where Flagged = 0 AND SalesID = '" & gUserID & "'
UNION ALL
Select RecordID, DiaryDate AS [inDate]
From tblOrderDetails
Where Flagged=0 And ManID ='" & gUserID & "'
UNION ALL
Select RecordID, CareDate As [inDate]
From tblOrderDetails
Where Flagged = 0 And CareID ='" & gUserID & "'
) As dT Group By RecordID"
cmd.CommandText = strSQL
cmd.Connection = CnMaster
cmd.CommandType = CommandType.Text
Dim RecordCount As Integer
RecordCount = 0
dDate = DateTime.MaxValue
Using reader As SqlDataReader = cmd.ExecuteReader()
While (reader.Read())
RecordCount += 1
Dim dt As DateTime = reader.GetDateTime(1)
If dt < dDate Then
dDate = dt
End If
End While
If dDate = DateTime.MaxValue Then
dDate = DateTime.MinValue
End If
End Using
cmd.Dispose()
Return dDate
Catch ex As Exception
Error_Handler(ex, "GetEarliestDate", "Unable to Get The Earliest Date!")
End Try
Put in all 3 queries additional where:
where SentDate is not null ...
where DiaryDate is not null ...
where CareDate is not null ...

How to run multiple queries in qtp in one shot using single object

I have a excel sheet with a column named sqlQueries.
Every cell has a set of queries to run.
I am able to run sumple queries using qtp
But the cells that have multiple statements like for e.g in cell(x,6) the below query is present:
"
Use LDatabase
Exec sp_DropObjectIfExists '#tempTable';
Select col1 into #tempTable from maintable;
Update #tempTable set colv=5
Select count(1) as totalCount from #tempTable
"
The above is just an e.g. and not the exact sql query.
This entire set is in a single excel sheet's cell.
I want this to be executed using Qtp.
Currently, what I am doing in qtp is:
Set objconnection = CreateObject("ADODB.Connection")
objconnection.open"provider=blah blah blah"
Set objrecordset= CreateObject("ADODB.Recordset")
ws.cells(x,6).select ''''the above sql queries set is in this cell
Sqlquery1= ws.cells(x,6).value
objrecordset.Open Sqlquery1. objconnection
Value1=objrecordset.Fields.Item(0)
For the Last line above I am getting error saying
"Items cannot be found in the collection corresponding to requestef name or ordinal"
I am assuming this is because there are multiple statements in a single cell which are to be excuted but only the first line that is "use LDatabase" is being executed. And not all the cell content.
Could you please help me execute the entire thing in a single shot.
Thanks!
Prefix your queries with SET NOCOUNT ON;. This will allow you to use temp tables and variables in your SQL statements.
The code below demonstates this. I've used early binding to make the code easier to read (Tools >> References >> Microsoft ActiveX Data Objects 2.8 Library).
Switch between these lines to test:
rs.Open QueryA, cn, adOpenForwardOnly, adLockReadOnly
rs.Open QueryB, cn, adOpenForwardOnly, adLockReadOnly
QueryA will fail. QueryB will return Jack.
' Demo of using SET NOCOUNT ON;.
' This option enabled the use of SQL vars and temp tables.
Sub Test()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
cn.Open "Driver={SQL Server};Server=YOUR-SEVER-NAME-HERE;Database=master;Trusted_Connection=Yes;"
' QueryA fails, while QueryB does not.
' Switch which line is commented out to test.
rs.Open QueryA, cn, adOpenForwardOnly, adLockReadOnly
'rs.Open QueryB, cn, adOpenForwardOnly, adLockReadOnly
' This line will raise an error with QueryA.
' This line will work with QueryB.
MsgBox rs.Fields(1).Value
rs.Close
cn.Close
End Sub
' Returns a sample query without NOCOUNT.
Public Function QueryA() As String
QueryA = " CREATE TABLE #ExampleA "
QueryA = QueryA & " ( "
QueryA = QueryA & " Id INT PRIMARY KEY, "
QueryA = QueryA & " Name VARCHAR(50) NOT NULL "
QueryA = QueryA & " ); "
QueryA = QueryA & ""
QueryA = QueryA & " INSERT INTO #ExampleA (Id, Name) "
QueryA = QueryA & " VALUES "
QueryA = QueryA & " (1, 'Jack'), "
QueryA = QueryA & " (2, 'Jill') "
QueryA = QueryA & " ; "
QueryA = QueryA & ""
QueryA = QueryA & " SELECT * FROM #ExampleA "
End Function
' Returns a sample query with NOCOUNT.
Public Function QueryB() As String
QueryB = " SET NOCOUNT ON; "
QueryB = QueryB & ""
QueryB = QueryB & " CREATE TABLE #ExampleA "
QueryB = QueryB & " ( "
QueryB = QueryB & " Id INT PRIMARY KEY, "
QueryB = QueryB & " Name VARCHAR(50) NOT NULL "
QueryB = QueryB & " ); "
QueryB = QueryB & ""
QueryB = QueryB & " INSERT INTO #ExampleA (Id, Name) "
QueryB = QueryB & " VALUES "
QueryB = QueryB & " (1, 'Jack'), "
QueryB = QueryB & " (2, 'Jill') "
QueryB = QueryB & " ; "
QueryB = QueryB & ""
QueryB = QueryB & " SELECT * FROM #ExampleA "
End Function
I've embedded the two versions of my query in a couple of, ugly, functions. They're hard to read but easy to share. Below is a clean version of the working query. Remove the first line for the non-working variant.
SET NOCOUNT ON;
CREATE TABLE #ExampleA
(
Id INT PRIMARY KEY,
Name VARCHAR(50) NOT NULL
);
INSERT INTO #ExampleA (Id, Name)
VALUES
(1, 'Jack'),
(2, 'Jill')
;
SELECT * FROM #ExampleA;

Access 2010 report constrained between dates

I am trying to get a form setup to launch various reports based on different criteria and I am having problems getting one of the reports that is a GroupBy/Count/Sum based SQL Data source to work between 2 unbound textboxes serving as a FromDate and a ToDate.
VBA script - calling report from form (frmRptFeedback):
Private Sub cmdPrint_Click()
If Not chkPrintPreview Then
Set Application.Printer = Application.Printers.Item(cboPrinter.Value)
End If
Dim strCondition As String
Dim strFromDate As String
Dim strToDate As String
strFromDate = txtFromDate.Value
strToDate = txtToDate.Value
Select Case opgOptions
Case 1 ' Feedback By Employee
If IsNull(cboEmployee.Value) Then
strCondition = "DateSubmitted BETWEEN '" & strFromDate & "' AND '" & strToDate & "'"
Else
strCondition = "RespEmp = '" & cboEmployee.Value & "' AND DateSubmitted BETWEEN '" & _
strFromDate & "' AND '" & strToDate & "'"
End If
Call OpenReport("rptFeedbackByEmp", IIf(chkPrintPreview, acViewPreview, acViewNormal), strCondition)
Case 2 ' Feedback By Team
If IsNull(cboTeam.Value) Then
strCondition = "DateSubmitted BETWEEN '" & strFromDate & "' AND '" & strToDate & "'"
Else
strCondition = "EmpType = '" & cboTeam.Value & "' AND DateSubmitted BETWEEN '" & _
strFromDate & "' AND '" & strToDate & "'"
End If
Call OpenReport("rptFeedbackByTeam", IIf(chkPrintPreview, acViewPreview, acViewNormal), strCondition)
Case 3 ' Feedback By Project #
If IsNull(txtProjectID) Then
strCondition = "DateSubmitted BETWEEN '" & strFromDate & "' AND '" & strToDate & "'"
Else
strCondition = "ProjectID = " & txtProjectID & "AND DateSubmitted BETWEEN '" & _
strFromDate & "' AND '" & strToDate & "'"
End If
Call OpenReport("rptFeedbackByProject", IIf(chkPrintPreview, acViewPreview, acViewNormal), strCondition)
End Select
If Not chkPreview Then
Set Application.Printer = Nothing
End If
End Sub
SQL query - initially pulling data into main SQL View (vueRptFeedback):
SELECT f.FeedbackID, f.BFID, bf.ProjectID, p.ProjectName, e2.Name AS PM, e1.Name AS RespEmp,
et.Description AS EmpType, f.SubByInits, f.DateSubmitted, f.QtyIssues,
f.EstHoursImpact, f.PlusDelta, f.Notes, f.HowResolved
FROM dbo.tblEmployee e2
INNER JOIN dbo.tblProject p
INNER JOIN dbo.tblBookingForm bf
ON p.ProjectID = bf.ProjectID
ON e2.EmployeeID = p.Scope_PM_EmployeeID
RIGHT OUTER JOIN dbo.tblEmployeeType et
INNER JOIN dbo.tblEmployee e1
ON et.EmployeeTypeID = e1.EmployeeTypeID
INNER JOIN dbo.tblFeedback f
ON e1.EmployeeID = f.ResponsibleEmpID
ON bf.BookingFormID = f.BFID
SQL query - current recordsource for report by Project ID (vueRptFeedbackByProject):
SELECT ProjectID, ProjectName, RespEmp, COUNT(FeedbackID) AS CountReports,
SUM(QtyIssues) AS SumIssues, SUM(EstHoursImpact) AS SumHours
FROM vueRptFeedback
WHERE (DateSubmitted
BETWEEN CONVERT(DATETIME, [Forms]![frmRptFeedback]![txtFromDate], 102)
AND CONVERT(DATETIME, [Forms]![frmRptFeedback]![txtToDate], 102))
GROUP BY ProjectID, RespEmp, ProjectName, DateSubmitted
ORDER BY ProjectID, RespEmp
I know my problem is in the WHERE clause as when I take it out, the report pulls fine but with all records, not the ones between those two dates. Once I can get the report to pull between the txtFromDate and txtToDate, I will probably need to change the OpenReport() to pass the txtFromDate and txtToDate as parameters instead of a Between X and Y, but I keep getting tripped up by syntax on the Recordsource of the report.
Fundamentally, you are conflating two SQL dialects - SQL Server SQL and MS Access SQL. There is no CONVERT() function in Access SQL syntax which appears to be the engine running the recordsource of the report and not the pass-through query, vueRptFeedback, run by MSSQL.
Consider using FORMAT() to align dates to ANSI datetime format: YYYY-MM-DD:
SELECT ProjectID, ProjectName, RespEmp, COUNT(FeedbackID) AS CountReports,
SUM(QtyIssues) AS SumIssues, SUM(EstHoursImpact) AS SumHours
FROM vueRptFeedback
WHERE (DateSubmitted
BETWEEN FORMAT([Forms]![frmRptFeedback]![txtFromDate], "YYYY-MM-DD")
AND FORMAT([Forms]![frmRptFeedback]![txtToDate], "YYYY-MM-DD"))
GROUP BY ProjectID, RespEmp, ProjectName, DateSubmitted
ORDER BY ProjectID, RespEmp
On the VBA side, you can still use Format() as many of Access's SQL functions derived from VBA functions (possibly, this is the reason Access SQL differs from its other RDMS counterparts who adhere to ANSI more due to the need to stay compatible in MS Office VBA context):
Dim strFromDate As String
Dim strToDate As String
strFromDate = Format(txtFromDate.Value, "YYYY-MM-DD")
strToDate = Format(txtToDate.Value, "YYYY-MM-DD")
...

Resources