I am working on an MS Access DB rewrite project that we are converting to a 2005 SQL server back-end/Winform front-end. I have a query in Access that I need to convert to run in SQL server. Here is the Access query:
UPDATE DISTINCTROW VAR, CancelsinTrans
INNER JOIN Trans ON (CancelsinTrans.ACCT = Trans.ACCT) AND (CancelsinTrans.ITEM_ID = Trans.ITEM_ID)
SET Trans.TRAN_CD = "1", Trans.LastUpdated = Date()
WHERE (((Trans.TRAN_CD)<>"1" Or (Trans.TRAN_CD) Is Null) AND
((CancelsinTrans.TRAN_DT)<[VAR]![Import1]) AND
((Trans.TRAN_DT)<[VAR]![Import1]));
The CancelsinTrans is a query that is pulling accounts from the Trans table - so basically it is joining on itself and performing an update.
Here is the CancelsInTrans query:
SELECT Trans.ACCT, Trans.TRAN_TYPE_CD, Trans.TRAN_SUBOR_CD, Trans.M_SRCE_CD, Trans.TRAN_RQST_CD, Trans.TRAN_AM, Trans.TRAN_DR_CR_CD, Trans.TRAN_CXL_CD, Trans.ACCTG_CD, Trans.ITEM_ID, Trans.TRAN_DT, Trans.TRAN_EXEC_TM, Trans.TRAN_QY, Trans.TRAN_NET, Trans.TRAN_EXEC_PR, Trans.M_SECURITY_NR, Trans.M_ORF_OR_ORDRNO, Trans.M_SEQ_NBR, Trans.TRAN_SETTL, Trans.M_ORDER_TAKER_ID, Trans.QUOTR_SEC, Trans.PROD_CD, Trans.SEC_CD, Trans.TRAN_EXEC_DT
FROM Trans
WHERE (((Trans.TRAN_TYPE_CD)="TR") AND ((Trans.TRAN_SUBOR_CD)="TR") AND ((Trans.TRAN_CD)="1") AND ((Trans.ACCTG_CD)="1"));
I am trying to figure out the best way to write this query. I was going to use a stored proc to run this update but should I use a table-function to get the set of records.
Any help would be great.
Thanks
The SQL Server equivalent would be something like the following:
Update Trans
Set TRAN_CD = '1'
, LastUpdated = GETDATE()
Where ( Trans.TRAN_CD <> '1' Or Trans.TRAN_CD Is Null )
And Trans.TRAN_DT < 'some var value'
And Exists (
Select 1
From CancelsinTrans As C1
Where C1.ACCT= Trans.ACCT
And C1.ITEM_ID = Trans.ITEM_ID
And C1.TRAN_DT < 'some var value'
)
In this case, through your parameterized query, you would replace some var value with the value from [VAR]![Import1] which I presume was a form value.
UPDATE
Given that the CancelsInTran query encapsulates the Trans table, you can eliminate the join like so:
Update Trans
Set TRAN_CD = '1'
, LastUpdated = GetDate()
Where TRAN_TYPE_CD = 'TR'
And TRAN_SUBOR_CD = 'TR'
And ACCTG_CD = '1'
And ( TRAN_CD <> '1' Or TRAN_CD Is Null )
And TRAN_DT < 'some value'
Related
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
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)
I'm trying to move from SQL Server to an Oracle database. I have to move my stored procedure from SQL Server to Oracle that do a query from multiple table with an INNER JOIN. I am trying to clarify few things here.
SQL Server stored procedure:
[dbo].[QueryAll]
#score1_min int = 0,
#score1_max int = 999,
#type1 varchar (1) = '%',
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM FUNIJ1 uni
INNER JOIN CAPI99 api99 on api99.application_id = uni.application_id
INNER JOIN CAPI41 api41 on api41.application_id = uni.application_id
INNER JOIN CAPI10 api10 on api10.application_id = uni.application_id
WHERE
api10.score1 BETWEEN #score1_min AND #score1_max
AND uni.type1 LIKE #type1
END
And my Oracle procedure
create or replace PROCEDURE QUERYALL
(
SCORE1_MIN IN NUMBER DEFAULT 0
, SCORE1_MAX IN NUMBER DEFAULT 999
, TYPE IN VARCHAR2
)
AS
BEGIN
SELECT *
FROM FUNIJ1 uni
INNER JOIN CAPI99 on CAPI99.APPLICATION_ID = uni.APPLICATION_ID
INNER JOIN CAPI41 on CAPI41.APPLICATION_ID = uni.APPLICATION_ID
INNER JOIN CAPI10 on CAPI10.APPLICATION_ID = uni.APPLICATION_ID
WHERE
CAPI10.score1 BETWEEN score1_min AND score1_max
AND uni.type LIKE type
END REPOQUERYALL ;
I used % as default query parameter to return all values in SQL Server
in case of no input from user. I am not sure what I have to use in Oracle as default value to return all.
List item Oracle is using new term INTO following to SELECT *. I am not sure whether I need to use INTO or cursor in this case. I don't know WHICH will be appropriate here and HOW to use it.
I'd appreciate if anybody can transfer this SQL Server to an Oracle procedure. I am not sure that my Oracle is 100% correct.
Here is what you need to understand about Oracle stored procedure - unlike in SQL Server, you can't just do SELECT ... in any programming block, unless this is subselect or select... into....
If the goal is to return record set from procedure, in Oracle, you have to add a Sys_RefCursor output parameter and open this ref cursor with your select statement.
You're not far away - check this example .And remember, when you do Open <cursor_name> FOR ..., what comes after FOR can be dynamic SQL string or just compiled SQL.
Here is the code that worked for me with Sys_Cursor. Thanks #TS for the help that guide me to this answer.
create or replace PROCEDURE QUERYALL
(
o_Cursor OUT SYS_REFCURSOR
)
AS
BEGIN
O_Cursor := NULL;
OPEN O_Cursor FOR
SELECT * FROM FUNIJ1
INNER JOIN CAPI99 on CAPI99.APPLICATION_ID = FUNIJ1 .APPLICATION_ID
INNER JOIN CAPI41 on CAPI41.APPLICATION_ID = FUNIJ1 .APPLICATION_ID
INNER JOIN CAPI10 on CAPI10.APPLICATION_ID = FUNIJ1 .APPLICATION_ID
WHERE
----
----
END QUERYALL;
When you use this procedure in Java to display the table, you need to call Sys_Cursor into Resultset.
String sp= "{CALL QUERYALL(?)}"; // Procedure calling with Sys_Cursor
cst = con.prepareCall(sql);
cst.registerOutParameter(1, OracleTypes.CURSOR);
cst.executeUpdate();
rs = (ResultSet) cst.getObject(1);
while(rs.next()) {
----
----
}
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.
##IDENTITY returns the ID of the last row inserted, I want to retrieve the ID of the last row updated.
Here is my query:
UPDATE [Table]
SET Active = 1,
Subscribed = 1,
RenewDate = GETDATE(),
EndDate = DATEADD(mm,1,getdate()),
WHERE SC = #SC
AND Service = #Ser
How do I get the ID of this updated row?
The column is called TableID and I'm not using it in the query.
You cannot retrieve an ID since there is no ID being inserted.....
But you can:
just query the table using the same criteria as in your UPDATE:
SELECT TableID
FROM dbo.Table
WHERE SC = #SC AND Service = #Ser -- just use the same criteria
use the OUTPUT clause on the UPDATE to get that info:
UPDATE [Table]
SET Active = 1,
Subscribed = 1,
RenewDate = GETDATE(),
EndDate = DATEADD(mm,1,getdate())
OUTPUT Inserted.TableId -- output the TableID from the table
WHERE SC = #SC AND Service = #Ser
Read more about the OUTPUT clause on Technet - it can be used on INSERT and DELETE as well
you can try using this:
OUTPUT INSERTED.TableID
in your code it would look like this:
UPDATE [Table]
SET Active = 1,
Subscribed = 1,
RenewDate = GETDATE(),
EndDate = DATEADD(mm,1,getdate())
OUTPUT INSERTED.TableID
WHERE SC = #SC
AND Service = #Ser
Hope this helps.
I guess you need this one,
UPDATE [Table]
SET Active = 1,
Subscribed = 1,
RenewDate = GETDATE(),
EndDate = DATEADD(mm,1,getdate())
OUTPUT INSERTED.TABLE_PrimaryKeyID
WHERE SC = #SC
AND Service = #Ser
Main source: here
Try using
select ##identity gives last updated identity for the particular session
(or)
select scope_identity gives last updated identity for the particular scope
(or)
select ident_curr('tablename') give the last updated identity regardless of the session or scope but for that particular table.