How to convert T-SQL that deals with OPENXML, WITH and BIGINT? - sql

I'm trying to convert a procedure to use in SQL Azure. I first got an error on OPENXML saying it's not supported on SQL Azure, then I find out it can be replaced with nodes.
But I'm not sure how to convert the WITH (Id BIGINT '.') part. I know WITH creates a subquery but what is the '.' doing here?
CREATE Procedure [dbo].[DocsR]
#ids xml -- <Ids><Id>1</Id><Id>2</Id></Ids>
AS
BEGIN
SET NOCOUNT ON;
DECLARE #IdsXml xml
exec sp_xml_preparedocument #IdsXml OUTPUT, #Ids
SELECT
DoctId,
DocNm
FROM
Docs
WHERE
--DocId IN (SELECT Id FROM OPENXML(#IdsXml, '/Ids/Id', 2) WITH (Id BIGINT '.'))
DocId IN (SELECT Id FROM #IdsXml.nodes('/Ids/Id') WITH (Id BIGINT '.'))
END
GO
Error:
Incorrect syntax near the keyword 'with'. If this statement is a common
table expression, an xmlnamespaces clause or a change tracking context clause,
the previous statement must be terminated with a semicolon.

Try the following:
SELECT
DoctId,
DocNm
FROM
Docs
WHERE
DocId IN (SELECT Id = node.value('.', 'INT')
FROM #IdsXml.nodes('/Ids/Id') AS R(node))

Related

SQL Server XQuery.modify syntax issues, unable to resolve

I have a SQL Server 2016 table dbo.Agent which has a column called XMLDta, but its datatype is nvarchar(max).
The data within this column is structured as XML, like so:
<misc id="m12345">
<pauth id="p12345">
<AEmail/>
<ipauth id="i12345">
<IProd>xxxxxx</IProd>
<achannel id="00000000">
<Chan>ABCEDF</Chan>
<Selected>1</Selected>
</achannel>
<Seg>ZZZ</Seg>
<states id="s12345">
<Sel>0</Sel>
<Avail>1</Avail>
<State>XX</State>
</states>
<states id="s67890">
<Sel>1</Sel>
<Avail>1</Avail>
<State>YY</State>
</states>
<LOB>FFFF</LOB>
<AUW>abc#email.com</AUW>
<WQue>10</WQue>
<AgChan>ABCEDF,</AgChan>
<State>XX,YY,</State>
<Status>Active</Status>
</ipauth>
<ipauth>
....
</ipauth>
</pauth>
</misc>
Trying to modify the Status node in above xml using following XQuery.modify() SQL/XQuery statement:
UPDATE dbo.Agent
SET CAST(xmldta AS xml).modify('replace value of (/misc/pauth/ipauth/Status/text()) with "Pending"')
WHERE agID = 209
But I keep getting the following error:
Incorrect syntax near '('.
Also tried using this SQL:
DECLARE #Dta As XML
DECLARE #id AS INT = 209
SELECT #Dta = CAST(XMLDta AS XML)
FROM dbo.Agent
WHERE agID = #id
UPDATE dbo.Agent
SET #Dta.modify('replace value of (/misc/pauth/ipauth/Status/text()) with "Pending"')
WHERE agID = 209
But I still get the same error:
Incorrect syntax near '('.
How do I correctly structure my SQL statement so it can reference the XMLDta column within the XQuery.modify function?
Please remember XMLDta column has a datatype of nvarchar(max) in the dbo.Agent table.
If I am going about this wrong way, please let me know and suggest better path.
Thanks and any guidance would be greatly appreciated.
Rebecca
Please take into account that the SQL Server XQuery .modify() method will update just one single XML element at a time.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata NVARCHAR(MAX));
INSERT INTO #tbl (xmldata) VALUES
(N'<misc id="m12345">
<pauth id="p12345">
<AEmail/>
<ipauth id="i12345">
<IProd>xxxxxx</IProd>
<achannel id="00000000">
<Chan>ABCEDF</Chan>
<Selected>1</Selected>
</achannel>
<Seg>ZZZ</Seg>
<states id="s12345">
<Sel>0</Sel>
<Avail>1</Avail>
<State>XX</State>
</states>
<states id="s67890">
<Sel>1</Sel>
<Avail>1</Avail>
<State>YY</State>
</states>
<LOB>FFFF</LOB>
<AUW>abc#email.com</AUW>
<WQue>10</WQue>
<AgChan>ABCEDF,</AgChan>
<State>XX,YY,</State>
<Status>Active</Status>
</ipauth>
<ipauth>....</ipauth>
</pauth>
</misc>');
-- DDL and sample data population, end
DECLARE #Dta AS XML
, #param VARCHAR(30) = 'Pending'
, #id AS INT = 1;
SET #Dta = (SELECT TRY_CAST(xmldata AS XML) FROM #tbl WHERE ID = #id);
SET #Dta.modify('replace value of (/misc/pauth/ipauth/Status/text())[1] with sql:variable("#param")');
UPDATE #tbl
SET xmldata = TRY_CAST(#Dta AS NVARCHAR(MAX))
WHERE ID = 1;
SELECT * FROM #tbl;

T-SQL get substring

I am looking to get an order number from a column named KEY_Ref, this ref column have various contents, but some rows look like this
LINE_NO=15^ORDER_NO=176572^RELEASE_NO=1^
Now I am interested in getting the value for ORDER_NO (176572 in this case)
How would I (In SQL Server) go about getting this (Or other) value from the main string
The logic is always
key1=value1^key2=value2^key3=value3^
You can use string_split():
select t.*, s.orderno
from t outer apply
(select stuff(s.value, 1, 9, '') as orderno
from string_split(t.key_ref, '^') s
where s.value like 'ORDER_NO=%'
) s;
Here is a db<>fiddle.
this is going to be a bit lengthy answer however if your SQL server version doesn't support string_split function you may use this.
declare #str varchar(100) = 'LINE_NO=15^ORDER_NO=176572^RELEASE_NO=1^'
declare #substr1 varchar(50) = substring(#str,charindex('^',#str)+1,len(#str))
declare #substr2 varchar(50) = substring(#substr1,charindex('=',#substr1)+1,charindex('^',#substr1)-charindex('=',#substr1)-1)
select #substr2 as 'order number'
the final variable will produce the desired value and you must merge the above queries to a single query that can fetch the value from the table in a single select statement.
this will work only if the pattern doesn't deviate from the one you've mentioned.

Is there any way to convert varchar to int value in sql?

I have a query like this when I pass the values into in operator in sql it shows:
Conversion failed when converting the varchar value '3,4,9' to data type int.
How can I solve the issue?
declare #values varchar(100)
set #values = '3,4,9'
select #values
select * from CmnItemType where ItemTypeID in (#values)
No. You can use string_split() or a similar user-defined function:
where itemtypeid in (select try_convert(int, value) from string_split(#values))
What I usually do is use table variable, like this one:
DECLARE #values TABLE (id INT)
INSERT INTO #values (id) VALUES (3),(4),(9)
SELECT id FROM #values
From that, you could simply do a join to your tables.
If you are creating a stored procedure, you can use a TVP to pass parameters, here is the Microsoft doc on that. With a TVP, your code can simply call your SP with a list and you will be able to join it in the SP.
Hope this will help.

How to put result of one column inside a string variable?

I try to select number of rows and then put them into string variable such as 1,2,3,4,5, but get this error :
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
I use MSSQL SERVER
DECLARE #CodeNameString VARCHAR(MAX)
SELECT #CodeNameString = STUFF(
(
SELECT dbo.CharterReference.TicketNo+','
FROM dbo.CharterReference
),
1,
1,
''
)
SELECT #CodeNameString
How can i fix this?
If you want the values in #CharterReference, you can use the following
Declare #CharterReference table (TicketNo int)
Insert Into #CharterReference values
(1),(2),(3),(4),(5),(6),(7),(8)
Declare #CodeNameString varchar(Max) = '>>>'
Select #CodeNameString =replace(concat(#CodeNameString ,',',TicketNo),'>>>,','')
From #CharterReference
Where TicketNo between 1 and 5
Order By TicketNo
Select #CodeNameString
Returns
1,2,3,4,5
Or you can use a little XML
Select #CodeNameString=Stuff((Select ',' +cast(TicketNo as varchar(25))
From #CharterReference
Where TicketNo between 1 and 5
For XML Path ('')
),1,1,'')
The error message is complaining because you have multiple rows returned, and that is not allowed in the way you have done this.
Rearranging to a normal looking select statement, and then lopping off the last comma afterwards would work around this:
DECLARE #CodeNameString VARCHAR(MAX);
set #CodeNameString = '';
SELECT #CodeNameString = TicketNo + ','
FROM dbo.CharterReference;
SELECT left(#CodeNameString, len(#CodeNameString)-1) as CodeNameString;
The SQL-based solution requires you to use recursive SQL for this. The syntax is typically DBMS-specific, and guessing by the syntax you're using in the example, O believe your engine calls this feature "recursive CTE".
The alternative is to cursor over the result set with the individual row and construct the string append in your client program.
Yet another alternative is to use the PL/SQL dialect of your system. You can then write an SQL procedure where you do the cursoring over the result set and the string appending. You can expose this SQL procedure as a callable module to your client programs.

SQL datatype for using a string sentence

I want to create a SQL Server stored procedure like this:
CREATE PROCEDURE dbo.uspGetCharacterID
(#characterName vchar(1000))
as
SELECT c.charatcer_full
FROM CHARACTER c (nolock)
WHERE character_full IN (#characterName)
ORDER BY C.characterID
From code, #charactername I am passing --> 'Batman in latest movies', 'Superman in latest movies'
But in code its returning zero rows.
NOTE: if I run the same select query in SQL with those string, it successfully returns two rows.
QUESTION: which datatype should be used, so that requirement is satisfied?
'Varchar' and 'Text' didn't work.
Please guide
Thanks
CREATE TYPE tp_names AS
TABLE
(
name VARCHAR(1000) NOT NULL
)
GO
CREATE PROCEDURE
uspGetCharacterID (#names tp_names READONLY)
AS
SELECT c.character_full
FROM CHARACTER c
WHERE character_full IN
(
SELECT name
FROM #names
)
ORDER BY
characterID
GO
DECLARE #names tp_names
INSERT
INTO #names
VALUES
('Batman in latest movies'),
('Superman in latest movies')
EXEC uspGetCharacterID
#names = #names