VB.net access data from 2 select statement in stored procedure - sql-server

I am trying to access the result from 2 select statement in vb.net, but I can only access the data from the 1st select statement.
CREATE PROCEDURE [dbo].[pr_testproc]
AS
BEGIN
SET NOCOUNT ON;
SELECT
comp_name, p_center, branch_id
FROM
tbl_company B
INNER JOIN
tbl_b_office X ON X.batch_id = B.tran_id
WHERE
X.office_stat = 1
ORDER BY
comp_name ASC;
SELECT
xcomp_name, xp_center, xbranch_id
FROM
tbl_company B
INNER JOIN
tbl_b_office X ON X.batch_id = B.tran_id
WHERE
X.office_stat = 0
AND MONTH(X.post_dt) = MONTH(GETDATE())
AND YEAR(X.post_dt) = YEAR(GETDATE())
ORDER BY
comp_name ASC;
END
Example if I try to get the result for data in 2nd table
getData(intRow).xcomp_name
This gets the error:
Object reference not set to an instance of an object.
But this would get the data
getData(intRow).comp_name
will get the value of the field.

Collect the output data to a Dataset so that, you can take the result of first select query from the DataTable in the 0th index of the dataset.
this May help you:
Dim myDataSet=GetDataSetFromSP("yourSPName")
Dim FirstResult As DataTable=myDataSet.Tables(0)
Dim SecontResult As DataTable=myDataSet.Tables(1)
Here you have to write the function that will execute the SP and return DataSet.

You could also combine the 2 queries into one.
CREATE PROCEDURE [dbo].[pr_testproc]
AS
BEGIN
SET NOCOUNT ON;
SELECT
comp_name, p_center, branch_id, xcomp_name, xp_center, xbranch_id
FROM
tbl_company B
INNER JOIN
tbl_b_office X ON X.batch_id = B.tran_id
WHERE
X.office_stat = 1
OR
(
X.office_stat = 0
AND MONTH(X.post_dt) = MONTH(GETDATE())
AND YEAR(X.post_dt) = YEAR(GETDATE())
)
ORDER BY
comp_name ASC;
END
Then in the code, check the value of office_stat and continue accordingly.

Related

select query on a table is hanging when a stored procedure to update the table is run

I've a simple stored procedure to update a table as follows:
This sp is updating the table properly. But when I execute select query on po_tran table, its hanging.
Is there any mistake in the stored procedure..?
alter procedure po_tran_upd #locid char(3)
as
SET NOCOUNT ON;
begin
update t
set t.lastndaysale = (select isnull(sum( qty)*-1, 0)
from exp_tran
where exp_tran.loc_id =h.loc_id and
item_code = t.item_code and
exp_tran.doc_date > dateadd(dd,-30,getdate() )
and exp_tran.doc_type in ('PI', 'IN', 'SR')),
t.stk_qty = (select isnull(sum( qty), 0)
from exp_tran
where exp_tran.loc_id =h.loc_id and
item_code = t.item_code )
from po_tran t, po_hd h
where t.entry_no=h.entry_no and
h.loc_id=#locid and
h.entry_date> getdate()-35
end
;
Try the following possible ways to optimize your procedure.
Read this article, where I have explained the same example using CURSOR, Here I also have updated a field of the table using CURSOR.
Important: Remove Subquery, As I can see you have used a subquery to update the field.
You can use Join or Save the result of your query in the temp variable and you can use that variable while update.
i.g
DECLARE #lastndaysale AS FLOAT
DECLARE #stk_qty AS INT
select #lastndaysale = isnull(sum( qty)*-1, 0) from exp_tran where exp_tran.loc_id =h.loc_id and
item_code = t.item_code and exp_tran.doc_date > dateadd(dd,-30,getdate() ) and exp_tran.doc_type in ('PI', 'IN', 'SR')
select #stk_qty = isnull(sum( qty), 0) from exp_tran where exp_tran.loc_id =h.loc_id and item_code = t.item_code
update t set t.lastndaysale =#lastndaysale,
t.stk_qty = #stk_qty
from po_tran t, po_hd h where t.entry_no=h.entry_no and h.loc_id=#locid and h.entry_date> getdate()-35
This is just a sample example you can do need full changes in that.
I added a possibly more performant update, however, I do not fully understand your question. If "any" query is running slow against the po_tran, then I suggest you examine the indexing on that table and ensure it has a proper clustered index. If "this" query is running slow then I suggest you look into "covering indexes". The two fields entry_no and item_code seem like good candidates to include in a covering index.
update t
set t.lastndaysale =
CASE WHEN e.doc_date > dateadd(dd,-30,getdate() AND e.doc_type in ('PI', 'IN', 'SR') THEN
isnull(sum(qty) OVER (PARTITION BY e.loc_id, t.item_code) *-1, 0)
ELSE 0
END,
t.stk_qty = isnull(SUM(qty) OVER (PARTITION BY e.loc_id, t.item_code),0)
from
po_tran t
INNER JOIN po_hd h ON h.entry_no=t.entry_no AND h.entry_date> getdate()-35
INNER JOIN exp_tran e ON e.loc_id = h.loc_id AND e.itesm_code = t.item_code
where
h.loc_id=#locid

SQL stored procedure to update a table column by calculating the difference from 2 other tables

I have 3 tables in SQL Server that are exactly the same. I am trying to write a stored procedure to get the value of 2 columns from 2 tables and update the 3rd table with the difference. These are the 3 tables:
Current
Proposed
Final
I am passing in rfds_processing_id. It is similar to an order number and contains multiple rows, so matching has to be done on rfds_processing_id, type, sector, and position.
I need to match every row from the 3 tables and then subtract the value of Current.qty from Final.qty and update the Proposed.qty with the difference. It also needs to update Proposed.model with the value of Final.model (when Proposed.qty > 0). Currently it is setting every row to the same value. I'm assuming I need to loop through the rows. What should that look like?
ALTER PROCEDURE [dbo].[CalculateProposedAntennas]
(
#rfds_processing_id uniqueidentifier = null,
#id uniqueidentifier OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
UPDATE P
SET qty = (F.qty - C.qty) , model = F.model
FROM Proposed_Antenna P
INNER JOIN Final_Antenna F
ON P.rfds_processing_id = F.rfds_processing_id
INNER JOIN Current_Antenna C
ON F.rfds_processing_id = C.rfds_processing_id
WHERE
F.rfds_processing_id = C.rfds_processing_id
AND F.sector = C.sector
AND F.type = C.type
AND F.position = C.position
RETURN
END
The following query should do what you want:
ALTER PROCEDURE [dbo].[CalculateProposedAntennas]
(
#rfds_processing_id uniqueidentifier = null,
#id uniqueidentifier OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
UPDATE P
SET P.qty = F.qty - C.qty
,P.model = CASE WHEN Proposed.qty > 0 THEN F.model ELSE NULL END
FROM Proposed_Antenna P
INNER JOIN Final_Antenna F
ON F.rfds_processing_id = P.rfds_processing_id AND F.sector = P.sector AND F.type = P.type AND F.position = P.position
INNER JOIN Current_Antenna C
ON C.rfds_processing_id = P.rfds_processing_id AND C.sector = P.sector AND C.type = P.type AND C.position = P.position
RETURN
END
I highly recommend you to create a [UID] column in all three of your tables - the unique identifier case can be generated as below, the generated key is of varbinary type which is far better than string comparison in joins
select [UID] = HashBytes('MD5',rfds_processing_id+type+sector+position)

Stored procedure error: Msg 512, Level 16, State 1, Procedure sp_ActFTC, Line 64 Subquery returned more than 1 value

After executing a stored procedure, I get the following error:
Msg 512, Level 16, State 1, Procedure sp_ActFTC, Line 64
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I have two tables in the database, FTC_Alt and FichaTecnicaComp, and I need to update the FichaTecnicaComp table on a given date.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_ActFTC]
AS
DECLARE #Codigo NVARCHAR(20),
#DataAlteracao DATE,
#Categoria NVARCHAR(20),
#catord INT,
#SubCategoria NVARCHAR(255),
#subcatord INT,
#Ordem INT,
#CodigoComp NVARCHAR(10),
#DesignacaoComp NVARCHAR(50),
#QuantidadeComp NVARCHAR(25),
#UnidadeComp NVARCHAR(5),
#intRowCount INT,
#upAction NVARCHAR(255);
SELECT #Codigo = ft_alt.codigo
FROM ft_alt;
SELECT #DataAlteracao = ft_alt.dataalteracao
FROM ft_alt;
SELECT Categoria = ftc_alt.categoria
FROM ftc_alt;
SELECT catord = ftc_alt.catord
FROM ftc_alt;
SELECT SubCategoria = ftc_alt.subcategoria
FROM ftc_alt;
SELECT subcatord = ftc_alt.subcatord
FROM ftc_alt;
SELECT Ordem = ftc_alt.ordem
FROM ftc_alt;
SELECT CodigoComp = ftc_alt.codigocomp
FROM ftc_alt;
SELECT DesignacaoComp = ftc_alt.designacaocomp
FROM ftc_alt;
SELECT QuantidadeComp = ftc_alt.quantidadecomp
FROM ftc_alt;
SELECT UnidadeComp = ftc_alt.unidadecomp
FROM ftc_alt;
SELECT #intRowCount = ##RowCount;
SET #upAction = 'Composição nutricional actualizada/alterada'
BEGIN
IF (#DataAlteracao = (SELECT CONVERT(DATE, GETDATE())))
BEGIN
SET NOCOUNT ON
UPDATE [dbo].[FichaTecnicaComp]
SET [Codigo] = #Codigo,
[DataAlteracao] = #DataAlteracao,
categoria = ftc_alt.categoria,
catord = ftc_alt.catord,
subcategoria = ftc_alt.subcategoria,
subcatord = ftc_alt.subcatord,
ordem = ftc_alt.ordem,
codigocomp = ftc_alt.codigocomp,
designacaocomp = ftc_alt.designacaocomp,
quantidadecomp = ftc_alt.quantidadecomp,
unidadecomp = ftc_alt.unidadecomp
FROM [dbo].[FichaTecnicaComp]
JOIN ftc_alt ON [dbo].[FichaTecnicaComp].[Codigo] = (SELECT ft_alt.codigo
FROM ft_alt)
AND [dbo].[FichaTecnicaComp].Ordem = (SELECT FTC_Alt.Ordem
FROM FTC_Alt)
END
END
he expected result is that data in FichaTecnicaComp is updated from FTC_Alt.
Which doesn't happen.
It should be noted that the FichaTecnicaComp has the following working triggers: insertion, update and delete.
If you need the code of those triggers just ask.
Sub queries used in this context can only return a single value, whereas your sub queries are just returning all values of the Ordem and codigo columns. Use the columns directly in the ON clause instead of as sub-selects. You will also want use aliases instead of the full table names. Using only the keyword JOIN will default to an INNER JOIN, which is what I'm assuming you intend to use, however explicitly stating this will help with readability. The first sub query in your post uses ft_alt, instead of ftc_alt, but since this is the only reference to this table I'm guessing this is a typo?
BEGIN
SET NOCOUNT ON
UPDATE FTC
SET
FTC.[Codigo] = FT.Codigo,
FTC.[DataAlteracao] = FT.dataalteracao,
FTC.categoria = ALT.categoria,
FTC.catord = ALT.catord,
FTC.subcategoria = ALT.subcategoria,
FTC.subcatord = ALT.subcatord,
FTC.ordem = ALT.ordem,
FTC.codigocomp = ALT.codigocomp,
FTC.designacaocomp = ALT.designacaocomp,
FTC.quantidadecomp = ALT.quantidadecomp,
FTC.unidadecomp = ALT.unidadecomp
FROM [dbo].[FichaTecnicaComp] FTC
INNER JOIN ft_alt FT ON FTC.Codig = FT.Codigo
INNER JOIN ftc_alt ALT ON FTC.Ordem = ALT.Ordem
END
The error message itself says that one of the sub queries used in this stored procedure returns more than one record, while your update statement can handle only one returned row the way it is written. If you run below queries one by one, you will know where is the problem. Either you need to fix the subquery or may need to use IN instead of = in main query. I hope that helps.
(SELECT ft_alt.codigo
FROM ft_alt)
AND
[dbo].[FichaTecnicaComp].Ordem =
(SELECT FTC_Alt.Ordem
FROM FTC_Alt
And also run below independently.
SELECT FTC_Alt.Ordem
FROM FTC_Alt

Update row with values from select on condition, else insert new row

I'm need to run a calculation for month every day. If the month period, exists already, I need to update it, else I need to create a new row for the new month.
Currently, I've written
declare #period varchar(4) = '0218'
DECLARE #Timestamp date = GetDate()
IF EXISTS(select * from #output where period=#period)
/* UPDATE #output SET --- same calculation as below ---*/
ELSE
SELECT
#period AS period,
SUM(timecard.tworkdol) AS dol_local,
SUM(timecard.tworkdol/currates.cdrate) AS dol_USD,
SUM(timecard.tworkhrs) AS hrs,
#Timestamp AS timestamp
FROM dbo.timecard AS timecard
INNER JOIN dbo.timekeep ON timecard.ttk = timekeep.tkinit
INNER JOIN dbo.matter with (nolock) on timecard.tmatter = matter.mmatter
LEFT JOIN dbo.currates with (nolock) on matter.mcurrency = currates.curcode
AND currates.trtype = 'A'
AND timecard.tworkdt BETWEEN currates.cddate1
AND currates.cddate2
WHERE timekeep.tkloc IN('06','07') AND
timecard.twoper = #period
SELECT * FROM #output;
How can simply update my row with the new data from my select.
Not sure what RDBMS are you using, but in SQL Server something like this would update the #output table with the results of the SELECT that you placed in the ELSE part:
UPDATE o
SET o.dol_local = SUM(timecard.tworkdol),
SET o.dol_USD = SUM(timecard.tworkdol/currates.cdrate),
SET o.hrs = SUM(timecard.tworkhrs),
set o.timestamp = #Timestamp
FROM #output o
INNER JOIN dbo.timecard AS timecard ON o.period = timecard.twoper
INNER JOIN dbo.timekeep ON timecard.ttk = timekeep.tkinit
INNER JOIN dbo.matter with (nolock) on timecard.tmatter = matter.mmatter
LEFT JOIN dbo.currates with (nolock) on matter.mcurrency = currates.curcode
AND currates.trtype = 'A'
AND timecard.tworkdt BETWEEN currates.cddate1
AND currates.cddate2
WHERE timekeep.tkloc IN('06','07') AND
timecard.twoper = #period
Also, I think you want to do an INSERT in the ELSE part, but you are doing just a SELECT, so I guess you should fix that too
The answer to this will vary by SQL dialect, but the two main approaches are:
1. Upsert (if your DBMS supports it), for example using a MERGE statement in SQL Server.
2. Base your SQL on an IF:
IF NOT EXISTS (criteria for dupes)
INSERT INTO (logic to insert)
ELSE
UPDATE (logic to update)

stored procedure always returning one row result in sql server

I have a table like this in my sql server:
TransactID Dtid Sid
1086 5 4
1086 7 8
1086 4 3
i want to take corresponding name of Dtid and Sid from resepective table.so i created stored procedure like this:
ALTER procedure [dbo].[PDTDamageFetch]
#Carid NVARCHAR(50)
AS
BEGIN
SET NOCOUNT ON
declare #transid integer,#dtid integer,#sid integer,#Damage nvarchar(100),#side nvarchar(100)
select #transid= t.transactID from Transaction_tbl t where t.TBarcode=#Carid
select #dtid= tr.Dtid from TransactDamageAssign_tbl tr where tr.transactID=#transid
select #sid= tr.sid from TransactDamageAssign_tbl tr where tr.transactID=#transid
select #Damage=dt.DtName from DamageType_tbl dt where dt.Dtid=#dtid
select #side= ds.SName from DamageSide_tbl ds where ds.Sid=#sid
select #Damage,#side
end
then i executed my stored procedure passing corresponding carid..transactID of particular car id is 1086 but stored procedure always showing one row of data..how i can replicate my issue..my
expected out put at this stage is:
Damage Side
scrtch front
broken Back
damged side
Try this query instead of yours. You are just assining one value to a variable, and that's why you just get one row
SELECT * FROM Transaction_tbl t
INNER JOIN TransactDamageAssign_tbl tr ON tr.transactID = t.transactID
INNER JOIN DamageType_tbl dt ON dt.Dtid = tr.Dtid
INNER JOIN DamageSide_tbl ds ON ds.Sid = tr.sid
WHERE t.TBarcode=#Carid
I think you should try table variables or temp tables to list all records.
The way you are trying, will always return the very last row of matching condition.

Resources