passing parameters into stored procedures classic asp - sql

I've asked a similar question before and although I've attempted to fix my previous code i now end up with an error "Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another". I want to pass a single character as a parameter to query a database then use recordset to print out to a webpage. My classic asp code is below
Set objCon = CreateObject("ADODB.Connection")
Set objRS = CreateObject("ADODB.Recordset")
set objComm = CreateObject("ADODB.Command")
objCon.ConnectionString = "Provider=SQLOLEDB.1;Password=xxxx;Persist Security Info=True;User ID=xxxx;Initial Catalog=Movies;Data Source=xxxx-PC"
objCon.open objCon.ConnectionString
objComm.ActiveConnection = objCon.ConnectionString
objComm.CommandText = "Paging_Movies"
objComm.CommandType = adCmdStoredProc
Set objParameter = objComm.CreateParameter
objParameter.Name = "alphaChar"
objParameter.Type = adChar
objParameter.Direction = adParamInput
objParameter.Value = "a"
objComm.Parameters.Append objParameter
set objRs = objComm.Execute
Also my stored procedure is below -
CREATE PROCEDURE Paging_Movies
#alphaChar char(1)
AS
if #alphaChar = '#'
select * from Movies where movies like '[^a-z]%'
else
select * from Movies where movies like #alphaChar + '%'

Perhaps you're adding the parameter twice. Try to replace:
objComm.ActiveConnection = objCon.ConnectionString
objComm.CommandText = "Paging_Movies"
objComm.CommandType = adCmdStoredProc
Set objParameter = objComm.CreateParameter
objParameter.Name = "alphaChar"
objParameter.Type = adChar
objParameter.Direction = adParamInput
objParameter.Value = "a"
Set objParameter = objCommand.CreateParameter ("alphaChar", adChar, _
adParamInput, "a")
objComm.Parameters.Append objParameter
with just:
objCommand.CreateParameter ("alphaChar", 129, 1, 1, "a")
Edited as your comment suggests to use the numeric values for adChar (129) and adParamInput (1) from the W3Schools CreateParameter page.

Related

Problem in updating database with relationship one to many

I'm trying to update my database but I'm getting this error:
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.Data.OleDb.OleDbException: You cannot add or change a record because a related record is required in table 'ItemTypes'.
I'm not sure how to fix it.
I don't know what i need to show so I will just show most of everything.
I've tried to look for a solution and the solutions that I've found said that it's because I'm trying to update the field with a value that is different but I don't understand why because the field is suppose to be the same.
The databases I have the problem with
This is the html part:
<asp:DropDownList ID="ItemType" runat="server">
<asp:ListItem></asp:ListItem>
</asp:DropDownList></td>
This is my code at the PageLoad:
if (!Page.IsPostBack)
{
DataTable dtItem = s.GetItemByIdForUser(Session["ItemCode"].ToString(),Session["Name"].ToString());
ItemCode.Text = dtItem.Rows[0][0].ToString();
ItemName.Text = dtItem.Rows[0][1].ToString();
ItemDes.Text = dtItem.Rows[0][2].ToString();
DataTable Types = s.GetAllItemsTypes();
for (int i = 0; i < Types.Rows.Count; i++)
ItemType.Items.Add(Types.Rows[i][0].ToString());
ItemType.SelectedItem.Text = dtItem.Rows[0][3].ToString();
ItemPrice.Text = dtItem.Rows[0][4].ToString();
Stock.Text = dtItem.Rows[0][5].ToString();
SellerName.Text = dtItem.Rows[0][6].ToString();
Image1.ImageUrl = "~/ProjectPictures/" + dtItem.Rows[0][8].ToString();
}
This is my code that happens when i click at the update:
DataTable dtItem = s.GetItemByIdForUser(Session["ItemCode"].ToString(), Session["Name"].ToString());
i.ItemCode = ItemCode.Text;
i.Name = ItemName.Text;
i.Des = ItemDes.Text;
i.Type = ItemType.SelectedItem.ToString();
i.Price = ItemPrice.Text;
i.Stock = Stock.Text;
i.UserName = SellerName.Text;
if (Pic.HasFile)
{
Pic.SaveAs(Server.MapPath("ProjectPictures/") + Pic.FileName);
i.Pic = Pic.FileName;
}
else
{
i.Pic = dtItem.Rows[0][8].ToString();
}
s.UpdateItem(i, ItemCode.Text);
Session["ItemCode"] = null;
Response.Redirect("Main.aspx");
and this is the sql sentence
string sql = "UPDATE [Items] SET [ItemName]= '#p1' , [ItemDes] = '#p2' , [ItemType] = '#p3' , [Price] = '#p4' , [Stock] = '#p5', [ItemPic] = '#p6' where [ItemCode] = '" +itemCode+ "'";
OleDbCommand cmd = new OleDbCommand(sql);
cmd.Parameters.Add(new OleDbParameter("#p1", OleDbType.VarChar));
cmd.Parameters["#p1"].Value = i.Name;
cmd.Parameters.Add(new OleDbParameter("#p2", OleDbType.VarChar));
cmd.Parameters["#p2"].Value = i.Des;
cmd.Parameters.Add(new OleDbParameter("#p3", OleDbType.VarChar));
cmd.Parameters["#p3"].Value = i.Type;
cmd.Parameters.Add(new OleDbParameter("#p4", OleDbType.VarChar));
cmd.Parameters["#p4"].Value = i.Price;
cmd.Parameters.Add(new OleDbParameter("#p5", OleDbType.VarChar));
cmd.Parameters["#p5"].Value = i.Stock;
cmd.Parameters.Add(new OleDbParameter("#p6", OleDbType.VarChar));
cmd.Parameters["#p6"].Value = i.Pic;
The problem is in your update statement. You have single quotation marks surrounding the parameter names. This means that they are interpreted as literal strings and not as the names of the parameter. So your statement is telling the database to update the ItemType with the value '#p3', (which is not a value in your ItemTypes table hence the foreign key violation) and not with the value in the parameter. In fact your parameters are being totally ignored.
Please also remember when using OleDB that the parameter names are ignored. All that matters is that you provide the parameters in the correct order.
Change your sql to this:
string sql = "UPDATE [Items] SET [ItemName]= #p1 , [ItemDes] = #p2 , [ItemType] = #p3 , [Price] = #p4 , [Stock] = #p5, [ItemPic] = #p6 where [ItemCode] = '" +itemCode+ "'";

where clause in VBA doesn't return what I need

I am trying to filter a dataset that I am pulling in from access using VBA, but for some reason this code doesn't return the filtered results.
With BrokerData
.ActiveConnection = BrokerConn
.Source = "SELECT * FROM BP_Closed_Deals WHERE EMM_Name = 'JM' OR 'J-C E';"
.LockType = adLockReadOnly
.CursorType = adOpenForwardOnly
.Open
End With
The following is not valid SQL syntax:
WHERE EMM_Name = 'JM' OR 'J-C E'
You want:
WHERE EMM_Name = 'JM' OR EMM_Name = 'J-C E'
Which can also be expressed with the IN operator:
WHERE EMM_Name IN ('JM', 'J-C E')

How to get Scalar-value-function result VB.net form through stored procedure

VB.Net Code
' Getting Records Before Transfer to GL
Call OpenAccConnection(lblUserName.Text, lblPassword.Text)
Dim odcTotalsForTransferGL As OleDbCommand = New OleDbCommand("spPet_TotalsForTransferGL", conAccounts)
odcTotalsForTransferGL.CommandType = CommandType.StoredProcedure
' Parameter Assigning
Dim strCompanyCode As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#ComCod", OleDbType.VarChar, 2)
strCompanyCode.Direction = ParameterDirection.Input
Dim strLocationCode As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#LocCod", OleDbType.VarChar, 2)
strLocationCode.Direction = ParameterDirection.Input
Dim strPettyCashDate As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#PetDat", OleDbType.VarChar, 8)
strPettyCashDate.Direction = ParameterDirection.Input
Dim strBegVNo As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#BegVNo", OleDbType.Integer)
strBegVNo.Direction = ParameterDirection.Output
Dim strEndVNo As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#EndVNo", OleDbType.Integer)
strEndVNo.Direction = ParameterDirection.Output
Dim strVouTotal As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#VouTotal", OleDbType.Integer)
strVouTotal.Direction = ParameterDirection.Output
Dim decPetTotal As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#PetTotal", OleDbType.Decimal)
decPetTotal.Direction = ParameterDirection.Output
Dim intFinancialDates As OleDbParameter = odcTotalsForTransferGL.Parameters.Add("#FinancialDates", OleDbType.Integer)
intFinancialDates.Direction = ParameterDirection.Output
' Passing Parameters
' Company Code
strCompanyCode.Value = cboCompanyCode.SelectedItem.ToString.Substring(0, 2)
' Location Code
strLocationCode.Value = cboLocationCode.SelectedItem.ToString.Substring(0, 2)
' Petty Cash Date(Year & Month)
strPettyCashDate.Value = dtPettyCashDate.Value.Year.ToString + dtPettyCashDate.Value.Month.ToString("D2") + "01"
' Accounts Database Open
conAccounts.Open()
' Stored Procedure Process
Dim odrTotalsForTransferGL As OleDbDataReader = odcTotalsForTransferGL.ExecuteReader()
If odrTotalsForTransferGL.HasRows Then
Do While odrTotalsForTransferGL.Read
lblAccPeriod.Text = odrTotalsForTransferGL.GetValue(4).ToString.Substring(0, 4) + "/" + odrTotalsForTransferGL.GetValue(4).ToString.Substring(5, 4)
lblFiscalMonth.Text = odrTotalsForTransferGL.GetValue(4).ToString.Substring(9, 2)
lblBegVNo.Text = odrTotalsForTransferGL.GetValue(0).ToString
lblEndVNo.Text = odrTotalsForTransferGL.GetValue(1).ToString
lblPettyTotal.Text = odrTotalsForTransferGL.GetValue(3).ToString
Loop
End If
Stored Procedure
ALTER PROCEDURE [dbo].[spPet_TotalsForTransferGL]
-- Add the parameters for the stored procedure here
#ComCod as varchar(2),
#LocCod as varchar(2),
#PetDat as varchar(8),
#BegVNo as int OUT,
#EndVNo as int OUT,
#VouTotal as int OUT,
#PetTotal as decimal(12,2) OUT,
#FinancialDates as varchar(10) OUT
AS
BEGIN
SELECT MIN(PettyDetail.DPetVouNo),
MAX(PettyDetail.DPetVouNo),
MAX(PettyDetail.DPetVouNo) - MIN(PettyDetail.DPetVouNo),
ISNULL(SUM(PettyDetail.DPetAmount), 0)
FROM PettyDetail
WHERE (PettyDetail.DPetComCode = #ComCod) AND
(PettyDetail.DPetLocCode = #LocCod) AND
(YEAR(PettyDetail.DPetDate) = YEAR(CONVERT(Date,#PetDat,111))) AND
(MONTH(PettyDetail.DPetDate) = MONTH(CONVERT(Date,#PetDat,111)))
/* Getting Financial Dates */
EXECUTE #FinancialDates = dbo.fnApp_GetFinancialDates #PetDat
END
Scalar Function
ALTER FUNCTION [dbo].[fnApp_GetFinancialDates]
(
-- Add the parameters for the function here
#PetDat as varchar(8)
)
--RETURNS int(10)
RETURNS varchar(10)
AS
BEGIN
-- Declare the return variable here
--DECLARE #FinancialDates int(10)
DECLARE #FinancialDates varchar(10)
-- Add the T-SQL statements to compute the return value here
IF MONTH(CONVERT(date,#PetDat,111)) BETWEEN 4 AND 12
BEGIN
SELECT #FinancialDates = (SELECT
CAST((YEAR(CONVERT(date,#PetDat,111))) as varchar) +
CAST((YEAR(CONVERT(date,#PetDat,111)) + 1) as varchar) +
REPLICATE('0',(2-(LEN(CAST((MONTH(CONVERT(date,#PetDat,111)) - 3) as varchar))))) + (CAST((MONTH(CONVERT(date,#PetDat,111)) - 3) as varchar)))
END
ELSE
BEGIN
SELECT #FinancialDates = (SELECT
CAST((YEAR(CONVERT(date,#PetDat,111)) - 1)as varchar) +
CAST((YEAR(CONVERT(date,#PetDat,111))) as varchar) +
CAST((MONTH(CONVERT(date,#PetDat,111)) + 9) as varchar))
END
-- Return the result of the function
RETURN #FinancialDates
END
Above function #FinancialDates value didn't return to the .Net form. But other results are return to form.
Can any one please help me to solve this problem. Procedure & Function run correctly in Query Manager.
Two options :
Option 1 : change EXECUTE #FinancialDates = dbo.fnApp_GetFinancialDates #PetDat,
to :
SET #FinancialDates = dbo.fnApp_GetFinancialDates(#PetDat)
Option 2 : Include your fnApp_GetFinancialDates function in your SELECT statement (and you could just remove the #FinancialDates as varchar(10) OUT parameter statement.
ALTER PROCEDURE [dbo].[spPet_TotalsForTransferGL]
-- Add the parameters for the stored procedure here
#ComCod as varchar(2),
#LocCod as varchar(2),
#PetDat as varchar(8)
AS
BEGIN
SELECT MIN(PettyDetail.DPetVouNo) AS 'BegVNo',
MAX(PettyDetail.DPetVouNo) AS 'EndVNo',
MAX(PettyDetail.DPetVouNo) - MIN(PettyDetail.DPetVouNo) AS 'VouTotal',
ISNULL(SUM(PettyDetail.DPetAmount), 0) AS 'PetTotal'
dbo.fnApp_GetFinancialDates (#PetDat) AS 'FinancialDates'
FROM PettyDetail
WHERE (PettyDetail.DPetComCode = #ComCod) AND
(PettyDetail.DPetLocCode = #LocCod) AND
(YEAR(PettyDetail.DPetDate) = YEAR(CONVERT(Date,#PetDat,111))) AND
(MONTH(PettyDetail.DPetDate) = MONTH(CONVERT(Date,#PetDat,111)))
END
and for the option 2 VB code :
If odrTotalsForTransferGL.HasRows Then
Do While odrTotalsForTransferGL.Read
lblAccPeriod.Text = odrTotalsForTransferGL("FinancialDates").ToString.Substring(0, 4) + "/" + odrTotalsForTransferGL("FinancialDates").ToString.Substring(5, 4)
lblFiscalMonth.Text = odrTotalsForTransferGL("FinancialDates").ToString.Substring(9, 2)
lblBegVNo.Text = odrTotalsForTransferGL("BegVNo").ToString
lblEndVNo.Text = odrTotalsForTransferGL("EndVNo").ToString
lblPettyTotal.Text = odrTotalsForTransferGL("PetTotal").ToString
Loop
End If
edited : and don't forget to remove the following code because they are not necessary and will produce errors since the stored proc has no output parameters anymore:
Dim strBegVNo As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#BegVNo", OleDbType.Integer)
strBegVNo.Direction = ParameterDirection.Output
Dim strEndVNo As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#EndVNo", OleDbType.Integer)
strEndVNo.Direction = ParameterDirection.Output
Dim strVouTotal As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#VouTotal", OleDbType.Integer)
strVouTotal.Direction = ParameterDirection.Output
Dim decPetTotal As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#PetTotal", OleDbType.Decimal)
decPetTotal.Direction = ParameterDirection.Output
Dim intFinancialDates As OleDbParameter =
odcTotalsForTransferGL.Parameters.Add("#FinancialDates", OleDbType.Integer)
intFinancialDates.Direction = ParameterDirection.Output

SQL/Server function yielding different result when called from VBS

I have the following SQL/Server function defined in C# to detect when a vehicle has refuelled. I keep a context of the last fuel used so that I don't need to move a cursor back over the data:
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlDouble GetFuelRefill(SqlString ID, SqlString FuelLeft)
{
object _lastID = CallContext.GetData("lastID6");
object _fuelRefill = CallContext.GetData("fuelRefill");
double fuelRefill = _fuelRefill == null ? 0.0 : Convert.ToDouble(_fuelRefill);
object _lastFuelLeft = CallContext.GetData("lastFuelLeft");
double lastFuelLeft = _lastFuelLeft == null ? 0.0 : Convert.ToDouble(_lastFuelLeft);
double result = 0.0;
if ((_lastID == null) || (Convert.ToString(_lastID) != ID.Value) || (_lastFuelLeft == null))
{
fuelRefill = 0;
CallContext.SetData("lastFuelLeft", 0.0);
}
else if (!FuelLeft.IsNull)
{
double fl = Convert.ToDouble(FuelLeft.Value);
if ((fl > 0.0) && (lastFuelLeft > 0.0) && ((fl - lastFuelLeft) / fl * 100.0 >= 5.0))
fuelRefill += fl - lastFuelLeft;
CallContext.SetData("lastFuelLeft", FuelLeft.Value);
}
result = fuelRefill;
CallContext.SetData("lastID6", ID.Value);
CallContext.SetData("fuelRefill", fuelRefill);
return new SqlDouble(result);
}
For the purpose of repeating the problem I have created a small test table:
SequenceNo AssetID FuelLeft
1 PJ1 50
2 PJ1 49
3 PJ1 48
4 PJ1 98
5 PJ1 95
Then I execute the following command from SQL/Server Management Studio:
SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill
FROM TestTable ORDER BY SequenceNo
Which yields the following result that I expect:
SequenceNo Refill
1 0
2 0
3 0
4 50
5 50
However then I try executing the same query using ADO from VBScript:
const DatabaseName = "MyDB"
const DatabaseServer = "(local)"
const adOpenForwardOnly = 0
const adLockOptimistic = 3
Dim FSO : set FSO = CreateObject("Scripting.FileSystemObject")
Dim Conn : Set Conn = CreateObject("ADODB.Connection")
Conn.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Initial Catalog=" & DatabaseName & ";Server=" & DatabaseServer
Set Query = CreateObject("ADODB.Recordset")
Query.Open "SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill FROM TestTable ORDER BY SequenceNo", Conn, adOpenForwardOnly, adLockOptimistic
Set f = FSO.CreateTextFile("E:\Temp\Test.TXT", true)
do while not Query.EOF
f.WriteLine Query("SequenceNo") & ", " & Query("Refill")
Query.MoveNext
loop
Set FSO = Nothing
Query.Close
Conn.Close
The test.txt file contains the following:
1, 0
2, 0
3, 0
4, 0
5, 0
Doing some further debugging it appears that the call context isn't being saved for the duration of the query, but I wondered if anyone knows why and a way to solve it?
After further experimentation I found two solutions. One was to place the query inside a simple stored procedure such as:
CREATE PROCEDURE sp_Test
AS
BEGIN
SET NOCOUNT ON;
SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill
FROM TestTable ORDER BY SequenceNo
END
And the other was to change the VBS code to use a client-side cursor:
const DatabaseName = "MyDB"
const DatabaseServer = "(local)"
const adOpenForwardOnly = 0
const adLockOptimistic = 3
const adUseClient = 3
Dim FSO : set FSO = CreateObject("Scripting.FileSystemObject")
Dim Conn : Set Conn = CreateObject("ADODB.Connection")
Conn.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Initial Catalog=" & DatabaseName & ";Server=" & DatabaseServer
Set Query = CreateObject("ADODB.Recordset")
Query.CursorLocation = adUseClient
Query.Open "SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill FROM TestTable ORDER BY SequenceNo", Conn, adOpenForwardOnly, adLockOptimistic
Set f = FSO.CreateTextFile("E:\Temp\Test.TXT", true)
do while not Query.EOF
f.WriteLine Query("SequenceNo") & ", " & Query("Refill")
Query.MoveNext
loop
Set FSO = Nothing
Query.Close
Conn.Close

Multidimensional array problem

I want to create a multidimensional array with 2 columns and have the row size a dynamic value. I then want to populate the multidimensional array with values from 2 different SQL queries (Microsoft).
The problem is That when the page loads it seems to be empty. How can Fill each column with he two different recordsets?
Or
At least return the total number of rows in the recordset?
Code below -
connectionstring = obj_ADO.getconnectionstring
Set objCon = CreateObject("ADODB.Connection")
Set objRS = CreateObject("ADODB.Recordset")
set objComm = CreateObject("ADODB.Command")
objCon.Open connectionstring
objComm.ActiveConnection = objCon.ConnectionString
objComm.CommandText = "A_Page_Paging"
objComm.CommandType = adCmdStoredProc
Set objParameter = objComm.CreateParameter
objParameter.Name = "selected_Char"
objParameter.Type = adChar
objParameter.Direction = adParamInput
objParameter.Size = 3
objParameter.Value = Selected_Button
objComm.Parameters.Append objParameter
set objRS = objComm.Execute
Increment = 0
Dim testArray()
while not objRS.EOF
Redim testArray(2, increment)
'--------------------------------------------
Page_ID = objRS("P_PageID")
connectionstring = obj_ADO.getconnectionstring
Set objConn = CreateObject("ADODB.Connection")
Set objRSS = CreateObject("ADODB.Recordset")
objConn.Open connectionstring
SQL = "Select P_Name as P_Name, P_Description as P_Description from L_PagePermission inner join A_Permission on p_permissionID = pp_PermissionID inner join A_Page on P_PageID = PP_PageID where P_PageID =" & Page_ID & " order by p_Name"
objRSS.open SQL, objConn
if not objRSS.EOF then
objRSS.MoveFirst
while not objRSS.EOF
'Fill Array
testArray(0, increment) = objRS("P_PageID")
objRSS.MoveNext
wend
objRSS.close
objConn.close
else
testArray(0, increment) = "-"
end if
Increment = Increment + 1
'--------------------------------------------
%>
<%
objRS.MoveNext
wend
objRS.Close
objCon.Close
response.Write testArray(0,5)
Figured it out myself by using preseve in the redim of my array so the code below fixed my problem -
'--------------------------------------------
Increment = 0
Dim testArray()
connectionstring = obj_ADO.getconnectionstring
Set objConn = CreateObject("ADODB.Connection")
Set objRSS = CreateObject("ADODB.Recordset")
objConn.Open connectionstring
SQL = "select * from a_permission inner join L_PagePermission on P_PermissionID = PP_PermissionID inner join A_Page on P_PageID = PP_PageID order by P_Name"
objRSS.open SQL, objConn
if not objRSS.EOF then
objRSS.MoveFirst
while not objRSS.EOF
Redim Preserve testArray(2, increment)
'Two Dimensional Array
testArray(0, increment) = objRSS("P_PageID")
testArray(1, increment) = objRSS("P_Name")
objRSS.MoveNext
Increment = Increment + 1
wend
objRSS.close
objConn.close
else
testArray(0, increment) = "-"
testArray(1, increment) = "-"
end if
'--------------------------------------------
'--------------------------------------------
Page_ID = objRS("P_PageID")
for i = 0 to (increment - 1)
if testArray(0, i) = Page_ID then
%>
<li style="" ="padding:0;margin:0;"><%=testArray(1,i)%></li>
<%
end if
next
'--------------------------------------------
If you run this query, do you get rows returned?
Select P_Name as P_Name, P_Description as P_Description from L_PagePermission inner join A_Permission on p_permissionID = pp_PermissionID inner join A_Page on P_PageID = PP_PageID where P_PageID =" & Page_ID & " order by p_Name