Oracle cursor variables - sql-server

I have this Oracle code that I need to convert in SQL Server but need help understanding what exactly it is doing . Since I have always avoided cursors it is still a mystery to me how they are used . please see the code below . This is placed in an insert trigger
CURSOR c1(table_name1 IN VARCHAR2)
IS
SELECT
a.begin, a.end, a.isnotactive, a.isactive, MIN(g.age) minage
FROM alltables a
LEFT OUTER JOIN people g ON (g.ageid = a.ageid)
WHERE table_name = table_name1
c1x_rec c1%ROWTYPE;
c1_rec c1%ROWTYPE;
I am particularly unsure about the following 3 lines . What exactly is it doing ? Where does the table_name1 gets its value from ?
WHERE table_name = table_name1
c1x_rec c1%ROWTYPE;
c1y_rec c1%ROWTYPE;

OPEN c1(table_name1) - this will open the cursor
FETCH c1 INTO variable - this is will fetch data into variable
You need to create variable, that must match with your select statement in your cursor, to fetch the data. For this, you use %ROWTYPE - that attribute provides a record type that represents a row. For example, your variables c1x_rec, c1y_rec have begin, end, isnoactive, isactive, minage fields, with each field declared as equivalent column type in alltables or people table.

Related

limitations in SQL used in Snowflake Dashboard Tiles

We are trying to use multi statements in Snowflake Dashboard tiles and do not quite understand the behaviour.
Let's say I create these 2 statements in my tile
SET MyVar = ( SELECT TOP 1 TABLE_NAME FROM DEV_CONTROL.INFORMATION_SCHEMA.TABLES WHERE NOT TABLE_NAME = :Subscription );
SELECT $MyVar;
If I highlight the first line and run it, I get a successful statement that does not return anything.
If I get back to my tile, I see "Statement executed successfully."
If I then go back to my SQL statements and highlights both, then run it, I get the name of the first table.
Going back to my dashboard, I now see the result of the second statement, my table name.
I find this both confusing and incoherent...
The data showed in the tile should reflect ALL the code I entered, not just what I happened to highlight and run the last time I looked at the code?...
Unfortunately, it's not documented well. As you mentioned, the tiles show only the result of the last executed query - at least this is what I observed on my tests.
Using Snowflake Scripting can be helpful here:
DECLARE
MyVar VARCHAR;
Rcount NUMBER;
BEGIN
SELECT TOP 1 TABLE_NAME INTO :MyVar FROM GOKHAN_DB.INFORMATION_SCHEMA.TABLES WHERE NOT TABLE_NAME LIKE 'TEST%' ORDER BY random();
SELECT IFNULL(ROW_COUNT,0) INTO :Rcount FROM GOKHAN_DB.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = :MyVar;
RETURN :MyVar || ' ' || :Rcount;
END;
The above code will be executed as a block.

what is the error? (SELECT [Data] FROM Split(#ProductName,','))

The stored procedure that used work with multiple parameters but it stops working.
I am trying to fix the stored procedure that used to work but suddenly create an error 'Invalid object name 'Split''. This is the procedure that someone else wrote so I am not exactly sure what 'Split' is. Is this some sort of command or what?
This is the stored Procedure that used to work but not anymore.
DECLARE #ProductName NVARCHAR(MAX) = '9x95dk36-2727-9401-8948-161740000000,150t3vh6-1230-4449-8846-173120000000'
SELECT
m.[member_id]
, m.external_member_id
, m.last_name
, m.first_name
, m.middle_name
, e.effective_date
,[termination_date]
, REPLACE(bhp.name_full_path,'CW > Medicaid > WI > SSI > ','') AS BHP
, pr.product_name
,pr.product_ID
INTO #ActiveSSIMembers
FROM
[Eligibility] as e
INNER JOIN Product as pr on e.product_id = pr.product_id
INNER JOIN Member as m on e.member_id = m.member_id
INNER JOIN BhpNode as bhp on m.bhp_node_id = bhp.bhp_node_id
WHERE
pr.product_ID IN (SELECT [Data] FROM Split(#ProductName,','))
We need to use multiple parameters for the query.
From the code you have posted, it seems Split is a Table-Valued User-Defined function that takes NVarchar parameter(seperated by ',') and returns rows of split values under the column name Data.
You are missing that user-defined function in your database where this query is being executed. Either this has been removed or you running the query in a different database.
Try navigating to Table-Valued Functions as below and make sure you have a function called Split in there(instead of 'TestFunction' in that image). If not, you can create your our function to split the values and add it to your database.
You can take help from this thread to create one

SQL - How can I return a value from a different table base on a parameter?

SQL - How can I return a value from a different table base on a parameter
First time poster, long time reader:
I am using a custom Excel function that allows be to pass parameters and build a SQL string that returns a value. This is working fine. However, I would like to choose among various tables based on the parameters that are passed.
At the moment I have two working functions with SQL statements look like this:
_______FUNCTION ONE________
<SQLText>
SELECT PRODDTA.TABLE1.T1DESC as DESCRIPTION
FROM PRODDTA.TABLE1
WHERE PRODDTA.TABLE1.T1KEY = '&PARM02'</SQLText>
_______FUNCTION TWO________
<SQLText>
SELECT PRODDTA.TABLE2.T2DESC as DESCRIPTION
FROM PRODDTA.TABLE2
WHERE PRODDTA.TABLE2.T2KEY = '&PARM02'</SQLText>
So I am using IF logic in Excel to check the first parameter and decide which function to use.
It would be much better if I could do a single SQL statement that could pick the right table based on the 1st parameter. Logically something like this:
_______FUNCTIONS COMBINED________
IF '&PARM02' = “A” THEN
SELECT PRODDTA.TABLE1.T1DESC as DESCRIPTION
FROM PRODDTA.TABLE1
WHERE PRODDTA.TABLE1.T1KEY = '&PARM02'
ELSE IF '&PARM02' = “B” THEN
SELECT PRODDTA.TABLE2.T2DESC as DESCRIPTION
FROM PRODDTA.TABLE2
WHERE PRODDTA.TABLE2.T2KEY = '&PARM02'
ELSE
DESCRIPTION = “”
Based on another post Querying different table based on a parameter I tried this exact syntax with no success
<SQLText>
IF'&PARM02'= "A"
BEGIN
SELECT PRODDTA.F0101.ABALPH as DESCRIPTION
FROM PRODDTA.F0101
WHERE PRODDTA.F0101.ABAN8 = '&PARM02'
END ELSE
BEGIN
SELECT PRODDTA.F4801.WADL01 as DESCRIPTION
FROM PRODDTA.F4801
WHERE PRODDTA.F4801.WADOCO = '&PARM02'
END</SQLText>
You could try using a JOIN statement.
http://www.sqlfiddle.com/#!9/23461d/1
Here is a fiddle showing two tables.
The following code snip will give you the values from both tables, using the Key as the matching logic.
SELECT Table1.description, Table1.key, Table2.description
from Table1
Join Table2 on Table1.key = Table2.key
Here's one way to do it. If PARM03='Use Table1' then the top half of the union will return records and vice versa. This won't necessarily product good performance though. You should consider why you are storing data in this way. It looks like you are partitioning data across different tables which is a bad idea.
SELECT PRODDTA.TABLE1.T1DESC as DESCRIPTION
FROM PRODDTA.TABLE1
WHERE PRODDTA.TABLE1.T1KEY = '&PARM02'
AND &PARM03='Use Table1'
UNION ALL
SELECT PRODDTA.TABLE2.T2DESC as DESCRIPTION
FROM PRODDTA.TABLE2
WHERE PRODDTA.TABLE2.T2KEY = '&PARM02'</SQLText>
AND &PARM03='Use Table2'

Retrieving data from a MS SQL 2012 table based on FK value from another table using stored procedure

I am working on MS SQL Server 2012. I have two tables - Associates and Clients and they have M:N relation so I have another table MapClientToAssociates where I have two foreign keys - ClientID and AssociateID. What I want to achieve is by providing a ClientID to take all the AssociateID's for this Client and then take all the information about each Associate (As I wrote, the relation is M:N so there can be several Associates for a certain client) and I want to return this data.
So basically I want to return rows containing :
`ID` - from `MapClientToAssociates`
`ClientID` - from `MapClientToAssociates`
`AssociateID` - from `MapClientToAssociates`
[column1] - from `Associates` (based on the `AssociateID` value)
[column2] - from `Associates` (based on the `AssociateID` value)
.
.
.
[columnN] - from `Associates` (based on the `AssociateID` value)
I tried to follow an existing code that is doing something pretty similar to that :
CREATE PROCEDURE [dbo].[usp_ClientGetAssociates]
#ClientID int
AS
BEGIN
If Exists (Select * From dbo.MapClientToAssociates map Where map.ClientID = #ClientID)
Begin
Declare #AssociateID int = (Select * map.AssociateID From dbo.MapClientToAssociates map Where map.ClientID = #ClientID)
And I get an error that I don't understand at the very beginning - Declare #AssociateID int = (Select * map.AssociateID - here map.AssociateID map is underscored in red saying Incorrect syntax near map) but I have to admit I don't have any experience with T-SQL or writing stored procedures and this seems like a standard stuff for a sproc to do so I would appreciate any help to make this sproc working and hopefully later I'll have the time to examine how exactly the code is working, but for now the most important thing for me is to make the sproc returns the result I want.
This clause (Select * map.AssociateID From dbo.MapClientToAssociates map Where map.ClientID = #ClientID) is returning a derived table of integer values. You are trying to assign it to a scalar (single) integer value, which does not make sense.
As for the actual syntax error, this :
Select * map.AssociateID From dbo.MapClientToAssociates map Where map.ClientID = #ClientID
is invalid because you would need to either remove the * or put a comma between it and the map.AssociateID.
This is how I would write this myself:
CREATE PROCEDURE [dbo].[usp_ClientGetAssociates]
#ClientID int
AS
BEGIN
Select act.*
From dbo.MapClientToAssociates map
Left Join dbo.Associates as act ON act.AssociateID = map.AssociateID
Where map.ClientID = #ClientID)
End
Unless I needed to consume the returned rowset in another SQL procedure or expression, then I would write it as a table-valued function instead.
CREATE PROCEDURE [dbo].[usp_ClientGetAssociates]
#ClientID int
AS
BEGIN
Select map.*, ass.*
from dbo.MapClientToAssociates map, dbo.Associates ass
where ass.AssociateID = map.AssociateID
and map.ClientID = #ClientID
If this response is wrong, can you provide a script for create and populate table and the full code of stored procedure?

How do I update an XML column in sql server by checking for the value of two nodes including one which needs to do a contains (like) comparison

I have an xml column called OrderXML in an Orders table...
there is an XML XPath like this in the table...
/Order/InternalInformation/InternalOrderBreakout/InternalOrderHeader/InternalOrderDetails/InternalOrderDetail
There InternalOrderDetails contains many InternalOrderDetail nodes like this...
<InternalOrderDetails>
<InternalOrderDetail>
<Item_Number>FBL11REFBK</Item_Number>
<CountOfNumber>10</CountOfNumber>
<PriceLevel>FREE</PriceLevel>
</InternalOrderDetail>
<InternalOrderDetail>
<Item_Number>FCL13COTRGUID</Item_Number>
<CountOfNumber>2</CountOfNumber>
<PriceLevel>NONFREE</PriceLevel>
</InternalOrderDetail>
</InternalOrderDetails>
My end goal is to modify the XML in the OrderXML column IF the Item_Number of the node contains COTRGUID (like '%COTRGUID') AND the PriceLevel=NONFREE. If that condition is met I want to change the PriceLevel column to equal FREE.
I am having trouble with both creating the xpath expression that finds the correct nodes (using OrderXML.value or OrderXML.exist functions) and updating the XML using the OrderXML.modify function).
I have tried the following for the where clause:
WHERE OrderXML.value('(/Order/InternalInformation/InternalOrderBreakout/InternalOrderHeader/InternalOrderDetails/InternalOrderDetail/Item_Number/node())[1]','nvarchar(64)') like '%13COTRGUID'
That does work, but it seems to me that I need to ALSO include my second condition (PriceLevel=NONFREE) in the same where clause and I cannot figure out how to do it. Perhaps I can put in an AND for the second condition like this...
AND OrderXML.value('(/Order/InternalInformation/InternalOrderBreakout/InternalOrderHeader/InternalOrderDetails/InternalOrderDetail/PriceLevel/node())[1]','nvarchar(64)') = 'NONFREE'
but I am afraid it will end up operating like an OR since it is an XML query.
Once I get the WHERE clause right I will update the column using a SET like this:
UPDATE Orders SET orderXml.modify('replace value of (/Order/InternalInformation/InternalOrderBreakout/InternalOrderHeader/InternalOrderDetails/InternalOrderDetail/PriceLevel[1]/text())[1] with "NONFREE"')
However, I ran this statement on some test data and none of the XML columns where updated (even though it said zz rows effected).
I have been at this for several hours to no avail. Help is appreciated. Thanks.
if you don't have more than one node with your condition in each row of Orders table, you can use this:
update orders set
data.modify('
replace value of
(
/Order/InternalInformation/InternalOrderBreakout/
InternalOrderHeader/InternalOrderDetails/
InternalOrderDetail[
Item_Number[contains(., "COTRGUID")] and
PriceLevel="NONFREE"
]/PriceLevel/text()
)[1]
with "FREE"
');
sql fiddle demo
If you could have more than one node in one row, there're a several possible solutions, none of each is really elegant, sadly.
You can reconstruct all xmls in table - sql fiddle demo
or you can do your updates in the loop - sql fiddle demo
This may get you off the hump.
Replace #HolderTable with the name of your table.
SELECT T2.myAlias.query('./../PriceLevel[1]').value('.' , 'varchar(64)') as MyXmlFragmentValue
FROM #HolderTable
CROSS APPLY OrderXML.nodes('/InternalOrderDetails/InternalOrderDetail/Item_Number') as T2(myAlias)
SELECT T2.myAlias.query('.') as MyXmlFragment
FROM #HolderTable
CROSS APPLY OrderXML.nodes('/InternalOrderDetails/InternalOrderDetail/Item_Number') as T2(myAlias)
EDIT:
UPDATE
#HolderTable
SET
OrderXML.modify('replace value of (/InternalOrderDetails/InternalOrderDetail/PriceLevel/text())[1] with "MyNewValue"')
WHERE
OrderXML.value('(/InternalOrderDetails/InternalOrderDetail/PriceLevel)[1]', 'varchar(64)') = 'FREE'
print ##ROWCOUNT
Your issue is the [1] in the above.
Why did I put it there?
Here is a sentence from the URL listed below.
Note that the target being updated must be, at most, one node that is explicitly specified in the path expression by adding a "[1]" at the end of the expression.
http://msdn.microsoft.com/en-us/library/ms190675.aspx
EDIT.
I think I've discovered the the root of your frustration. (No fix, just the problem).
Note below, the second query works.
So I think the [1] is some cases is saying "only ~~search~~ the first node".....and not (as you and I were hoping)...... "use the first node..after you find a match".
UPDATE
#HolderTable
SET
OrderXML.modify('replace value of (/InternalOrderDetails/InternalOrderDetail/PriceLevel/text())[1] with "MyNewValue001"')
WHERE
OrderXML.value('(/InternalOrderDetails/InternalOrderDetail/PriceLevel[text() = "NONFREE"])[1]', 'varchar(64)') = 'NONFREE'
/* and OrderXML.value('(/InternalOrderDetails/InternalOrderDetail/Item_Number)[1]', 'varchar(64)') like '%COTRGUID' */
UPDATE
#HolderTable
SET
OrderXML.modify('replace value of (/InternalOrderDetails/InternalOrderDetail/PriceLevel/text())[1] with "MyNewValue002"')
WHERE
OrderXML.value('(/InternalOrderDetails/InternalOrderDetail/PriceLevel[text() = "FREE"])[1]', 'varchar(64)') = 'FREE'
Try this :
;with InternalOrderDetail as (SELECT id,
Tbl.Col.value('Item_Number[1]', 'varchar(40)') Item_Number,
Tbl.Col.value('CountOfNumber[1]', 'int') CountOfNumber,
case
when Tbl.Col.value('Item_Number[1]', 'varchar(40)') like '%COTRGUID'
and Tbl.Col.value('PriceLevel[1]', 'varchar(40)')='NONFREE'
then 'FREE'
else
Tbl.Col.value('PriceLevel[1]', 'varchar(40)')
end
PriceLevel
FROM (select id ,orderxml from demo)
as a cross apply orderxml.nodes('//InternalOrderDetail')
as
tbl(col) ) ,
cte_data as(SELECT
ID,
'<InternalOrderDetails>'+(SELECT ITEM_NUMBER,COUNTOFNUMBER,PRICELEVEL
FROM InternalOrderDetail
where ID=Results.ID
FOR XML AUTO, ELEMENTS)+'</InternalOrderDetails>' as XML_data
FROM InternalOrderDetail Results
GROUP BY ID)
update demo set orderxml=cast(xml_data as xml)
from demo
inner join cte_data on demo.id=cte_data.id
where cast(orderxml as varchar(2000))!=xml_data;
select * from demo;
SQL Fiddle
I have handled following cases :
1. As required both where clause in question.
2. It will update all <Item_Number> like '%COTRGUID' and <PriceLevel>= NONFREE in one
node, not just the first one.
It may require minor changes for your data and tables.

Resources