display data using stored procedure vb.net - sql-server

if i click the search button, i keep on receiving an error at the value of IDNo, incorrect syntax near '11111' can someone help me?
With acc
IDNo = .IDNo
StartDate = DateTime.Parse(.StartDate).ToString("M/d/yyyy")
EndDate = DateTime.Parse(.EndDate).ToString("M/d/yyyy")
ProjectName = .ProjectName
ReferenceNo = .ReferenceNo
TaskCode = .TaskCode
FileName = .Filename
End With
dgAccomplishment.DataSource = Nothing
dgAccomplishmentPT.DataSource = Nothing
da = New SqlDataAdapter("dbo.process_time #User='" & IDNo & "' ,#From='" & StartDate & "',#To='" & EndDate & " 11:59:59 PM'", DB.GetConnection)
dt = New DataTable
da.Fill(dt)
dgAccomplishment.DataSource = dt
dgAccomplishment.Columns("ID").Visible = False
dgAccomplishment.Columns("TimeSave").Visible = False
da.Dispose()
dt.Dispose()
this is my stored procedure
SELECT a.ID, RTRIM(a.Last_User) [ID No.],
RTRIM(Users.FIRSTNAME + ' ' + Users.INITIAL + '. ' + Users.LASTNAME) [Name],
RTRIM(a.ProjectName) [Project Name],
a.ProjectNo, a.ProjectCode,
RTRIM(a.Filename) [Filename],
RTRIM(a.Filesize) [Filesize],
RTRIM(a.filesizeunit) [FileSizeUnit],
a.TimeSave [TimeSave]
from DBase.dbo.Acc a
INNER JOIN dbo.Users ON a.Last_User = Users.IDNo
WHERE a.Last_User in (#user)
and CONVERT(VARCHAR(10),timesave,101) BETWEEN #From AND #To
ORDER BY RTRIM(a.SubGroup), RTRIM(a.Last_User)
but when i try to run the procedure in a query it works well.

Because you are using string concatenation, you have the age old single quote problem: If IDNo value contains a single quote, then your query will fail.
What's worse, your code is susceptible to sql injection attacks.
You have to escape ALL parameters for single quotes, replacing them by 2 single quotes.
Best solution here: use parametrized sql

Related

Returning values from a stored procedure ASP Classic [duplicate]

This question already has an answer here:
operation not allowed when the object is closed when running more advanced query
(1 answer)
Closed 1 year ago.
I am having a problem to output the results from a stored procedure using SQL Server and ASP Classic. If I have a simple SELECT into the procedure, it works fine. But with the code shown here, I get an error.
I have this stored procedure in SQL Server:
ALTER PROCEDURE [dbo].[Sp_Teste]
#data varchar(8)
AS
BEGIN
--DROP TABLE IF EXISTS #TempSubs
DECLARE #TempSubs TABLE
(
PedidoID Int,
NumeroPedido Varchar(20),
SubstituidoPor Varchar(8000)
)
INSERT INTO #TempSubs (PedidoID, NumeroPedido, SubstituidoPor)
SELECT
P.ID, P.NumeroPedido,
STRING_AGG(CAST(IPA.Quantidade AS varchar(5)) + 'X ' + Pd.Nome, ', ') + ' por ' + STRING_AGG(CAST(IPA.Quantidade AS varchar(5)) + 'X ' + Pd2.Nome, ', ') AS SubstituidoPor
FROM
Pedidos P, Clientes C, Produtos Pd, ItensPedidosAjustado IPA, Produtos Pd2
WHERE
P.ID = IPA.PedidoId
AND P.ClienteId = C.ID
AND Pd.ID = IPA.ProdutoId
AND Faltante = 1
AND CONVERT(Date, P.DataPedido, 103) = CONVERT(Date, #data, 103)
AND (IPA.ProdutoSubstituidoId <> 0)
AND Pd2.ID = IPA.ProdutoSubstituidoId
AND ((P.StatusPedido <> 'Pause' AND P.StatusPedido <> 'PULOU ENTREGA' AND P.StatusPedido <> 'Pedido Cancelado') OR P.StatusPedido IS NULL)
GROUP BY
P.ID, P.NumeroPedido, IPA.ProdutoSubstituidoId
SELECT
(SELECT STRING_AGG(Indisponibilidade, ', ')
FROM #TempIndis A
WHERE A.PedidoID = P.ID) AS Indisponibilidade,
(SELECT STRING_AGG(SubstituidoPor, ', ')
FROM #TempSubs A
WHERE A.PedidoID = P.ID) AS Substituicao
FROM
Pedidos P, Clientes C, ItensPedidosAjustado IPA
WHERE
P.ID = IPA.PedidoId
AND P.ClienteId = C.ID
AND Faltante = 1
AND CONVERT(Date, P.DataPedido, 103) = CONVERT(Date, #data, 103)
AND ((P.StatusPedido <> 'Pause' AND P.StatusPedido <> 'PULOU ENTREGA' AND P.StatusPedido <> 'Pedido Cancelado') OR P.StatusPedido IS NULL)
AND P.PedidoCancelado = 0
GROUP BY
P.ID, P.NumeroPedido, C.Nome, C.Email, P.TipoAssinatura
ORDER BY
numeropedido
END
and this code in ASP Classic
db_conn = "Provider=SQLNCLI11;Server=xxxx;Database=BaseGaia;Uid=sqlserver;Pwd=xxxxx;"
set conn = server.createobject("adodb.connection")
set Cmd = Server.CreateObject("ADODB.Command")
'-------------------------------------------------------
conn.open (db_conn)
'-------------------------------------------------------
set rs = Server.CreateObject("ADODB.RecordSet")
sSQL = "EXEC Sp_Teste #data = '20210301'"
set rs = conn.execute (sSQL)
response.write rs.eof
I get this error:
ADODB.Recordset error '800a0e78'
Operation is not allowed when the object is closed.
/Atendimento/testestoreprocedure.asp, line 18
By default, SQL Server returns DONE_IN_PROC (rowcount) messages after INSERT statements, which ADO classic returns a closed/empty result sets. These must be consumed by invoking the NextRecordset method before the SELECT query results are available.
To avoid the extra coding, make a habit of specifying SET NOCOUNT ON; in stored procedures to suppress those unwanted results. Add that to the beginning of the proc code to avoid the error.

Insert multiple rows, count based on another table columns

I have 3 Tables. Item, StockDetail, Branch
I want to INSERT 2 of them at once. The Item and StockDetail table.
Item has 3 columns = ItemID, Title, Price.
StockDetail has 3 columns = ItemID, BranchID, Stock.
Branch has 1 column = BranchID.
In this code below, INSERT into Item works fine, but not for StockDetail table, it doesn't INSERT anything!
Now for the StockDetail if it works, I want to insert it with the condition below:
If you add an item, then it'll add this item with all existed BranchID.
That mean, every Branches will have this item.
e.g:
You add an item, while
Branch has 3 rows of BranchID = BR000, BR001, BR002.
It will insert to StockDetail with 3 rows as well, at once (single Query)
Complete result of StockDetail (single Query):
ItemID | BranchID | Stock
______________________________
IM000 | BR000 | 0
IM000 | BR001 | 0
IM000 | BR002 | 0
The Code:
'Add function'
'Insert to StockDetail'
Dim theCommand As New SqlCommand
Dim theDataAdapter As New SqlDataAdapter
Dim theDataTable As New DataTable
theCommand.Connection = theConnection
theCommand.CommandText = "INSERT INTO StockDetail VALUES(
'" & Me.TextBox_ItemID.Text & "',
SELECT COUNT(BranchID) FROM Branch,
'0'
)"
theDataAdapter.SelectCommand = theCommand
'Insert to Item'
theCommand.Connection = theConnection
theCommand.CommandText = "INSERT INTO Item VALUES('" & Me.TextBox_ItemID.Text & "', '" & Me.TextBox_Title.Text & "', '" & Me.TextBox_Price.Text & "')"
theDataAdapter.SelectCommand = theCommand
theDataAdapter.Fill(theDataTable)
DataGridView_Item.DataSource = theDataTable
theCommand.Dispose()
theDataAdapter.Dispose()
UPDATE:
The code below will tell you the working multiple INSERT, but not with the BranchID INSERT.
'Insert to StockDetail'
theConnection.Open()
Dim theCommand As New SqlCommand
Dim theDataAdapter As New SqlDataAdapter
theCommand.Connection = theConnection
theCommand.Parameters.Add("#ItemID", SqlDbType.VarChar).Value = Me.TextBox_ItemID.Text
theCommand.CommandText = "INSERT INTO StockDetail(ItemID, BranchID, Stock) SELECT #ItemID, COUNT(Branch.BranchID), '0' FROM Branch GROUP BY Branch.BranchID"
theDataAdapter.SelectCommand = theCommand
Using theDataAdapter
theCommand.ExecuteNonQuery()
theCommand.Parameters.Clear()
theCommand.Dispose()
theConnection.Close()
SqlConnection.ClearPool(theConnection)
End Using
What do I want now?
Well instead of inserting 1, 1, . . .
I'd like to INSERT it with BR000, BR001 . . . (Based on all existed BranchID)
Here is how you use a parameter in your first insert statement. I think you still have some very serious logic issues here though. This is going to insert 1 row into StockDetail and the values don't make any sense at all. You would be inserting the count of rows from the Branch table as the BranchID which is probably not what you really want. I suspect what you want is a row in this table for each Branch?
theCommand.CommandText = "INSERT INTO StockDetail(ItemID, BranchID, Price) VALUES(
#ItemID,
(SELECT COUNT(BranchID) FROM Branch),
0
)"
theCommand.Parameters.Add("#ItemID", SqlDbType.Varchar).Value = Me.TextBox_ItemID.Text;
I suspect what you really want is something more like this.
theCommand.CommandText = "INSERT INTO StockDetail(ItemID, BranchID, Price)
select #ItemID
, BranchID
, 0
from Branch";
theCommand.Parameter.Add("#ItemID", SqlDbType.Varchar).Value = Me.TextBox_ItemID.Text;
The SQL command text for the insert into StockDetail doesn't do what you say you want to happen. This code, though syntactically incorrect (if you want to use a SELECT as a value, you need to surround it in parentheses like this:
theCommand.CommandText = "INSERT INTO StockDetail VALUES(
'" & Me.TextBox_ItemID.Text & "',
(SELECT COUNT(BranchID) FROM Branch),
'0'
)"
), would insert your ID, a count of the number of branches you have, and a zero into the table.
For what you say you want to have happen, your code would look more like this:
theCommand.CommandText = "INSERT INTO StockDetail SELECT
'" & Me.TextBox_ItemID.Text & "',
BranchID, '0' FROM Branch
)"

vb table adapter does not allow more than one parameter in the IN clause

What I need to achieve is to send a list of unknown QTY of values to a Sql server NOT IN clause but can only achieve this with singular values. below is my Sql statement:
SELECT SorMaster.LastInvoice
, SorMaster.SalesOrder
, SorMaster.OrderStatus
, ArCustomer.RouteCode
, SorMaster.Customer
, SorMaster.CustomerName
, SorMaster.CustomerPoNumber
, SorMaster.OrderDate
, SorMaster.DateLastInvPrt
, ArInvoice.InvoiceBal1
, ArInvoice.TermsCode
FROM SorMaster AS SorMaster
INNER JOIN ArCustomer AS ArCustomer ON SorMaster.Customer = ArCustomer.Customer
INNER JOIN ArInvoice AS ArInvoice ON SorMaster.LastInvoice = ArInvoice.Invoice
WHERE (SorMaster.OrderStatus = '9')
AND (SorMaster.Branch LIKE 'J%')
AND (SorMaster.DocumentType = 'O')
AND (SorMaster.LastInvoice > #Last_Invoice)
AND (SorMaster.OrderDate > DATEADD(Month, - 4, GETDATE()))
AND (SorMaster.LastInvoice NOT IN (#ExclusionList))
ORDER BY SorMaster.LastInvoice
The #ExclusionList value is generated by this code as a string from a listbox:
Dim exclusion As String = ""
If MenuForm.ExclusionCB.Checked = True Then
For i = 0 To MenuForm.ExclusionLB.Items.Count - 2
exclusion = exclusion & MenuForm.ExclusionLB.Items(i) & ","
Next
exclusion = exclusion & MenuForm.ExclusionLB.Items(MenuForm.ExclusionLB.Items.Count - 1)
Else
exclusion = ""
End If
I have also tried sending the entire listbox as a collection.
Does anyone know how I can send more than one value (something like 1,2,3,4,5,6) and have sql understand that these is more than one? I won't have an issue with the SELECT statement changing, just as long as it returns the same information.
The reason I need this with the exception list, is our remote DB PK is on the Salesorder column and the local DB is on the LastInvoice column
Hope this makes sense. if you need more info, please let me know
You can send it as a string and use dynamic sql. Here's a simple example how to do that.
DECLARE #vals VARCHAR(50) = '1,2,3,4,5,6'
DECLARE #sql VARCHAR(MAX) = 'SELECT * FROM TABLE WHERE FIELD1 IN'
SET #sql = #sql + ' (' + #vals + ')'
-- #sql = 'SELECT * FROM TABLE WHERE FIELD1 IN (1,2,3,4,5,6)'
EXEC (#sql)

The conversion of a varchar data type to a datetime data type resulted in an out-of-range value

I am trying to read the data from a database and pass the dates that have been selected from a datetime picker as values for the query. I keep getting all kind of error messages that are becouse of the wrong data type, i think.
What am i doing wrong here??
Please help.
P
private void buttonRetrieveData_Click(object sender, EventArgs e)
{
openConnection();
//TODO: Add function te retrieve data between dates enteren in datetimepickers
DateTime datumVan = dateTimePickerVan.Value;
DateTime datumTot = dateTimePickerTot.Value;
string query = "select * from my_Table where date between '" + datumVan.ToShortDateString() + "' and '" + datumTot.ToShortDateString() + "' order by date desc";
DataSet dset = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter(query, connection);
SqlCommandBuilder cb = new SqlCommandBuilder(adapter);
adapter.Fill(dset, "my_Table");
dataGridView1.DataSource = dset;
dataGridView1.DataMember = "my_table";
adapter.Update(dset, "my_Table");
closeConnection();
}
I know that the SQL datetime type has a date range from : January 1, 1753, through December 31, 9999
And .NET datetime min value is 00:00:00.0000000, January 1, 0001.
I would recommend you to check that you are not falling between ranges.
That means that if your datetime picker is not initiated with SQL min value it might return an invalid SQL date.
Don't treat dates as strings. It's as simple as that, avoid converting them to strings in the first place, and you save yourself a whole heap of trouble.
So, instead of:
string query = "select * from my_Table where date between '" + datumVan.ToShortDateString() + "' and '" + datumTot.ToShortDateString() + "' order by date desc";
Have instead:
string query = "select * from my_Table where date between #Van and #Tot order by date desc";
And then add parameters to the command object:
adapter.SelectCommand.Parameters.AddWithValue("#Van",datumVan);
adapter.SelectCommand.Parameters.AddWithValue("#Tot",datumTot);
Let ADO.Net and SQL Server deal with the issue of translating .NET datetime values into SQL Server datetime values.
I faced a similar problem but my fix was simple:
Instead of
+ datumVan.ToShortDateString() + "' and '" + datumTot.ToShortDateString() +
I changed to
+ datumTot.ToShortDateString() + "' and '" + datumVan.ToShortDateString() +
Give it a try, if this helps.
Also, is your date is getting converted to string by use of ToShortDateString() but what format is that of your date in table ??
May be you can try following query as well:
select * from my_Table where CAST(date AS DATE) between CAST('" + ToShortDateString() + "' AS DATE) and CAST('" + datumTot.ToShortDateString() + "' AS DATE) order by date desc";

Where Is the Syntax Error in this SQL?

I've got a query that is pretty much the same as many others which are used in the same library... but I did a lot of copy&paste on the SQL to add features to each one which are all similar but slightly different. Just below is the section which gives me the SQL Parser error. It fires at the Set rs = line.
dim sql, rs
sql = "DECLARE #str VARCHAR(255); SELECT #str = LOWER(?);" &_
"SELECT * ( " &_
"SELECT TOP 8 * FROM [oca_search_model] WHERE " &_
"[osm_isactive] = 1 AND " &_
"LOWER([osm_category]) = LOWER(?) AND " &_
"(LOWER([osm_keywords]) LIKE '%'+#str+'%' OR " &_
"LOWER([osm_description]) LIKE '%'+#str+'%' OR " &_
"LOWER([osm_name]) LIKE #str+'%') " &_
"ORDER BY [osm_weight] DESC" &_
") AS T1 ORDER BY [T1].[osm_category] ASC, [osm_weight] DESC, [osm_name] ASC;"
Set rs = executeQuery(conn, sql, Array(searchString, category))
The specific error I receive is: [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near the keyword 'ORDER'. I have printed out the SQL that is generated from that concatenation and it is as follows (with added line breaks):
DECLARE #str VARCHAR(255);
SELECT #str = LOWER(?);
SELECT * (
SELECT TOP 8 * FROM [oca_search_model]
WHERE [osm_isactive] = 1
AND LOWER([osm_category]) = LOWER(?)
AND (
LOWER([osm_keywords]) LIKE '%'+#str+'%'
OR LOWER([osm_description]) LIKE '%'+#str+'%'
OR LOWER([osm_name]) LIKE #str+'%'
)
ORDER BY [osm_weight] DESC
) AS T1
ORDER BY [T1].[osm_category] ASC, [osm_weight] DESC, [osm_name] ASC;
For your reference, I have added the executeQuery function below.
Function executeQuery(ByRef connection, ByRef querytext, ByRef parameters)
Dim cmd, i, rs
Set cmd = Server.CreateObject("ADODB.Command")
cmd.CommandText = querytext
cmd.CommandType = 1
cmd.Prepared = True
For i = 0 To UBound(parameters)
cmd.Parameters.Append(createVarCharInputParameter(cmd, "", parameters(i)))
Next
Set cmd.ActiveConnection = connection
Set rs = cmd.Execute()
Set executeQuery = rs
End Function
I don't have access to run the query directly on the server with some test values. But a similar query without the LOWER([osm_category]) = LOWER(?) AND portion runs just fine. Can you spot the syntax error in that SQL? My colleagues and I can't seem to.
Please note that it is imperative that I retain the ordering of the top 8 records by the osm_weight field. More specifically, the query needs to: get the top 8 by weight that match the category, and string (and are active). Then I need to order them by category so they're "grouped" and then within each category I need them ordered by weight and then by name.
You're missing the FROM after the first SELECT *.
DECLARE #str VARCHAR(255);
SELECT #str = LOWER(?);
SELECT * FROM (
SELECT TOP 8 * FROM [oca_search_model]
WHERE [osm_isactive] = 1
AND LOWER([osm_category]) = LOWER(?)
AND (
LOWER([osm_keywords]) LIKE '%'+#str+'%'
OR LOWER([osm_description]) LIKE '%'+#str+'%'
OR LOWER([osm_name]) LIKE #str+'%'
)
ORDER BY [osm_weight] DESC
) AS T1
ORDER BY [T1].[osm_category] ASC, [osm_weight] DESC, [osm_name] ASC;
The error is in this section:
AND (
LOWER([osm_keywords]) LIKE '%'+#str+'%'
OR LOWER([osm_description]) LIKE '%'+#str+'%'
OR LOWER([osm_name]) LIKE #str+'%'
) ORDER BY [osm_weight] DESC
) AS T1
The AND is part of the where query, and you can use parenthesis here, no problem. Bu the ORDER BY seems to add a set of mismatched Parenthesis.
This query should (syntactically at least) work:
DECLARE #str VARCHAR(255);
SELECT #str = LOWER(?);
SELECT TOP 8 * FROM [oca_search_model]
WHERE [osm_isactive] = 1
AND LOWER([osm_category]) = LOWER(?)
AND (
LOWER([osm_keywords]) LIKE '%'+#str+'%'
OR LOWER([osm_description]) LIKE '%'+#str+'%'
OR LOWER([osm_name]) LIKE #str+'%'
)
ORDER BY [osm_weight] DESC

Resources