SQL replace value of with always random xml code - sql-server

I have the following SQL XML in several rows of a table (table is tbldatafeed column in configuration_xml). All of the UserName="" and Password="" is different each time for each row and does not repeat so I can not find/replace off of that. I am trying to write a query that finds all of those and replaces them with Username/Passwords I choose.
<DataFeed xmlns="http://www.tech.com/datafeed/dfx/2010/04" xmlns:plugin="pluginExtensions" Type="TODO" Guid="TODO" UserAccount="DF_LEAN_PopulateCommentsSubForm" Locale="en-US" DateFormat="" ThousandSeparator="" NegativeSymbol="" DecimalSymbol="" SendingNotifications="false" SendJobStatusNotifications="false" RecipientUserIds="" RecipientGroupIds="" RecipientEmailAddresses="" Name="CI_C11.01_Lean-Lean_Reject Comments_A2A" >
<Transporter>
<transporters:ArcherWebServiceTransportActivity xmlns:transporters="clr-namespace:ArcherTech.DataFeed.Activities.Transporters;assembly=ArcherTech.DataFeed" xmlns:out="clr-namespace:ArcherTech.DataFeed;assembly=ArcherTech.DataFeed" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:compModel="clr-namespace:ArcherTech.DataFeed.ComponentModel;assembly=ArcherTech.DataFeed" xmlns:channel="clr-namespace:ArcherTech.DataFeed.Engine.Channel;assembly=ArcherTech.DataFeed" xmlns:engine="clr-namespace:ArcherTech.DataFeed.Engine;assembly=ArcherTech.DataFeed" xmlns:kernel="clr-namespace:ArcherTech.Kernel.Channel;assembly=ArcherTech.Kernel" xmlns="clr-namespace:ArcherTech.DataFeed;assembly=ArcherTech.DataFeed" xmlns:schema="clr-namespace:System.Xml.Schema;assembly=System.Xml" xmlns:xmlLinq="clr-namespace:System.Xml.Linq;assembly=System.Xml" xmlns:domain="clr-namespace:ArcherTech.Common.Domain;assembly=ArcherTech.Common" xmlns:s="clr-namespace:System;assembly=mscorlib" x:Key="transportActivity" SearchType="ReportId" Uri="https://arcs-d" RecordsPerFile="100" ReportID="EC514865-88D5-49CE-A200-7769EC1C2A88" UseWindowsAuth="false" IsWindowsAuthSpecific="false" WindowsAuthUserName="i9XzCczAQ7J2rHwkg6wG9QF8+O9NCYJZP6y5Kzw4be0+cdvUaGu/9+rHuLstU736pnQrRcwmnSIhd6oPKIvnLA==" WindowsAuthPassword="+y0tCAKysxEMSGv1unpHxfg6WjH5XWylgP45P5MLRdQ6+zAdOLSVy7s3KJa3+9j2i83qn8I8K7+1+QBlCJT1E7sLQHWRFOCEdJgXaIr1gWfUEO+7kjuJnZcIEKZJa2wHyqc2Z08J2SKfdCLh7HoLtg==" WindowsAuthDomain="" ProxyName="" ProxyPort="8080" ProxyUsername="" ProxyPassword="" ProxyDomain="" IsProxyActive="False" ProxyOption="None" InstanceName="ARCS-D" TempFileOnSuccessAction="DoNothing" TempFileOnSuccessRenameString="" TempFileOnErrorAction="DoNothing" TempFileOnErrorRenameString="" Transform="{engine:DataFeedBinding Path=Transform}" SessionContext="{engine:DataFeedBinding Path=Session}">
<transporters:ArcherWebServiceTransportActivity.Credentials>
<NetworkCredentialWrapper UserName="TeSZmI1SqO0eJ0G2nDVU+glFg/9eZfeMppYQnPfbeg8=" Password="Slt4VHqjkYscWyCwZK40QJ7KOQroG9OTKr+RGt9bQjE=" />
</transporters:ArcherWebServiceTransportActivity.Credentials>
</transporters:ArcherWebServiceTransportActivity>
</Transporter>
</DataFeed>
I need to be able to set a value and replace it with a query
I have written the following
select #config_xml=configuration_xml from bldatafeed where datafeed_name = 'REMOVED'
update tbldatafeed set configuration_xml.modify(//*:NetworkCredentialWrapper/#UserName)[1] with "abc" ')
where datafeed_name = 'REMOVED'
This does the trick but it only works if I set the "abc" password each time in each area and in some cases I am running this against 50+ rows.
I also tried:
Declare #server nvarchar(max) = 'abc'
Declare #config_xml xml
select #config_xml=configuration_xml from bldatafeed where datafeed_name = 'REMOVED'
update tbldatafeed set configuration_xml.modify(//*:NetworkCredentialWrapper/#UserName)[1] with #server ')
where datafeed_name = 'REMOVED'
The error from this is that: XQuery [tbldatafeed.configuration_xml.modify()]: Top-level attribute nodes are not supported
What I would like to be able to do is set my variable and utilize that as I will be setting this up for multiple rows and unfortunately this error is making this a very difficult problem to solve.
Thanks for any help, this has kept me confused for a bit.

Use the function sql:variable() to use a variable in the XQuery expression.
declare #T table(X xml);
insert into #T values('<X UserName=""/>');
declare #UserName nvarchar(max) = 'abc'
update #T set
X.modify('replace value of (/X/#UserName)[1]
with sql:variable("#UserName")');

Related

How can I add defined parameter to (NEXT VALUE FOR) command?

CREATE OR ALTER FUNCTION sso.FINDSEQVALUE
(#sequence_text text)
RETURNS int
AS
BEGIN
DECLARE #value int;
DECLARE #sequence_value nvarchar(150);
SELECT #sequence_value = CAST(#sequence_text AS nvarchar(150));
SELECT #value = NEXT VALUE FOR #sequence_value;
RETURN #value;
END;
I have a problem. I have created a function on SQL Server and I defined the parameter as you can see. But I cannot add the this command #sequence_value after NEXT VALUE FOR command and I am getting an error.
Incorrect syntax near '#sequence_value'
Somebody can say that "You can use (SELECT NEXT VALUE FOR [SEQUENCE])". But I need this function because of there are two different database on my project. I need same function for databases. In addition function parameter need to be text.
What should I do?

For xml path query returns less records SQLSERVER

I need to generate the following XML structure from my SQL server view for four inspection type. The XML structure is as given below.
==
<Form FormIdentifier="Major Approvals (EPIC:EPIC Test)" CompanyCode="EPIC:EPIC Test" CompanyName="EPIC Test" VesselCode="EPBARN" SubmittedDate="2019-05-22T08:00:00" Status="Submitted" ApprovedDate="" ImoNumber="9251121">
<VesselName>EPIC BARNES</VesselName>
<VoyageNo></VoyageNo>
<IMO_Number>9251121</IMO_Number>
<SIRE>
<SIRERow>
<Company__Terminal2>SHELL</Company__Terminal2>
<Last_Inspected>2019-05-22T12:00:00+00:00</Last_Inspected>
<No_of_Obs>1</No_of_Obs>
<Risk_Rating>2</Risk_Rating>
<ve_Screening_Yes_No>3</ve_Screening_Yes_No>
<Comments>4</Comments>
<Expiry_Date>2019-05-23T12:00:00+00:00</Expiry_Date>
<Planned_Date>2019-05-31T12:00:00+00:00</Planned_Date>
<Planned_Port>SINGAPORE</Planned_Port>
<Plannng_Comments>5</Plannng_Comments>
<Observations_closed_out2>6</Observations_closed_out2>
</SIRERow>
</SIRE>
<Non_SIRE>
<Non_SIRERow>
<Company__Terminal1>BP</Company__Terminal1>
<Last_Inspected1>2019-05-01T12:00:00+00:00</Last_Inspected1>
<No_of_Obs1>1</No_of_Obs1>
<Risk_Rating1>2</Risk_Rating1>
<ve_Screening_Yes_No1>3</ve_Screening_Yes_No1>
<Comments1>4</Comments1>
<Expiry_Date1>2019-05-22T12:00:00+00:00</Expiry_Date1>
<Planned_Date1>2019-05-31T12:00:00+00:00</Planned_Date1>
<Planned_Port1>KERTEH</Planned_Port1>
<Planning_Comments>5</Planning_Comments>
<Observations_closed_out1>6</Observations_closed_out1>
</Non_SIRERow>
</Non_SIRE>
<Additional_Screening>
<Additional_ScreeningRow>
<Company__Terminal>EXXON</Company__Terminal>
<Last_Inspected2>2019-05-01T12:00:00+00:00</Last_Inspected2>
<No_of_Obs2>1</No_of_Obs2>
<Risk_Rating2>2</Risk_Rating2>
<ve_Screening_Yes_No2>3</ve_Screening_Yes_No2>
<Comments2>4</Comments2>
<Expiry_Date2>2019-05-22T12:00:00+00:00</Expiry_Date2>
<Planned_Date_>2019-05-31T12:00:00+00:00</Planned_Date_>
<Planned_Port2>OSAKA</Planned_Port2>
<Planning_Comments1>5</Planning_Comments1>
<Observations_closed_out>6</Observations_closed_out>
</Additional_ScreeningRow>
</Additional_Screening>
</Form>
=====
I have the written following query using for XML path and TYPE to create the above XML file.
it works fine as far as the syntax is concerned but never returns exact no of records. for one or two records it works fine and for more records, it either not generated fully or shows fewer records
DECLARE #vsl AS varchar(50) = 'Sea Fortune 1';
DECLARE #imo AS varchar(50) = '9293741';
SELECT 'Major Approvals (EPIC:EPIC Test)' AS "#FormIdentifier",
'EPIC:EPIC Test' AS "#CompanyCode",
'EPIC Test' AS "#CompanyName",
'' AS "#VesselCode",
GETDATE() AS "#SubmittedDate",
'Submitted' AS "#Status",
'' AS "#ApprovedDate",
#imo AS "#ImoNumber",
#vsl AS VesselName,
'' AS VoyageNo,
#imo AS IMONO,
(SELECT otmajorname AS "SIRERow/Company__Terminal2",
inspectedOn AS "SIRERow/Last_Inspected",
tobs AS "SIRERow/No_of_Obs2",
riskrating AS "SIRERow/Risk_Rating2",
pscreen AS "SIRERow/ve_Screening_Yes_No2",
comment AS "SIRERow/Comments2",
ApprovalTo AS "SIRERow/Expiry_Date",
plplandate AS "SIRERow/Planned_Date",
plport AS "SIRERow/Planned_Port",
remark AS "SIRERow/Plannng_Comments",
openobs AS "SIRERow/Observations_closed_out2"
FROM RptXMLepic
WHERE vtIMONo = #imo
AND InspType = 'SIRE'
FOR XML PATH('SIRE'), TYPE),
(SELECT otmajorname AS "Non_SIRERow/Company__Terminal2",
inspectedOn AS "Non_SIRERow/Last_Inspected",
tobs AS "Non_SIRERow/No_of_Obs2",
riskrating AS "Non_SIRERow/Risk_Rating2",
pscreen AS "Non_SIRERow/ve_Screening_Yes_No2",
comment AS "Non_SIRERow/Comments2",
ApprovalTo AS "Non_SIRERow/Expiry_Date",
plplandate AS "Non_SIRERow/Planned_Date",
plport AS "Non_SIRERow/Planned_Port",
remark AS "Non_SIRERow/Plannng_Comments",
openobs AS "Non_SIRERow/Observations_closed_out2"
FROM RptXMLepic
WHERE vtIMONo = #imo
AND InspType = 'NON- SIRE'
FOR XML PATH('Non_SIRE'), TYPE),
(SELECT otmajorname AS "CDIRow/Company__Terminal2",
inspectedOn AS "CDIRow/Last_Inspected",
tobs AS "CDIRow/No_of_Obs2",
riskrating AS "CDIRow/Risk_Rating2",
pscreen AS "CDIRow/ve_Screening_Yes_No2",
comment AS "CDIRow/Comments2",
ApprovalTo AS "CDIRow/Expiry_Date",
plplandate AS "CDIRow/Planned_Date",
plport AS "CDIRow/Planned_Port",
remark AS "CDIRow/Plannng_Comments",
openobs AS "CDIRow/Observations_closed_out2"
FROM RptXMLepic
WHERE vtIMONo = #imo
AND InspType = 'CDI'
FOR XML PATH('CDI'), TYPE),
(SELECT otmajorname AS "Addional_ScreeningRow/Company__Terminal2",
inspectedOn AS "Addional_ScreeningRow/Last_Inspected",
tobs AS "Addional_ScreeningRow/No_of_Obs2",
riskrating AS "Addional_ScreeningRow/Risk_Rating2",
pscreen AS "Addional_ScreeningRow/ve_Screening_Yes_No2",
comment AS "Addional_ScreeningRow/Comments2",
ApprovalTo AS "Addional_ScreeningRow/Expiry_Date",
plplandate AS "Addional_ScreeningRow/Planned_Date",
plport AS "Addional_ScreeningRow/Planned_Port",
remark AS "Addional_ScreeningRow/Plannng_Comments",
openobs AS "Addional_ScreeningRow/Observations_closed_out2"
FROM RptXMLepic
WHERE vtIMONo = #imo
AND InspType = 'Screen'
FOR XML PATH('Addional_Screening'), TYPE)
FOR XML PATH('Form');
GO
my data lies in the view RptXMLepic.
would you please help me where exactly the problem lies.
It was my mistake only . the query is perfect after a lot of searching on the net I found nothing. actually what I was doing just copying the XML output from the query window and pasting on some noteapd++ editor. But whole XML text was not getting copied. so finally I have clicked on on the output and it was blah blah! I mean it opened pretty well in SQL management studio only with all the data. sorry guys I am pretty relaxed now ..thanks

SQL Server float comparison in stored procedure

Unfortunately, I have two tables to compare float datatypes between. I've read up on trying casts, converts, using a small difference and tried them all.
The strange part is, this only fails when I'm executing a stored procedure. If I cut-and-paste the body of the stored procedure into a SSMS window, it works just great.
Sample SQL:
set #newEnvRiskLevel = -1
select
#newEnvRiskLevel = rl.RiskLevelId
from
LookupTypes lt
inner join
RiskLevels rl on lt.LookupTypeId = rl.RiskLevelTypeFk
where
lt.Code = 'RISK_LEVEL_ENVIRONMENTAL'
and convert(numeric(1, 0), rl.RiskFactor) = #newEnvScore
set #errorCode = ##ERROR
if (#newEnvRiskLevel = -1 or #errorCode != 0)
begin
print 'newEnvScore = ' + cast(#newEnvScore as varchar) + ' and risk level = ' + cast(isnull(#newEnvRiskLevel, -1) as varchar)
print 'ERROR finding environmental risk level for code ' + #itemCode + ', skipping record'
set #recordsErrored = #recordsErrored + 1
goto NEXTREC
end
My #newEnvScore variable is also a float converted to numeric(1, 0). I've verified that there are only 0, 1, 2, and 3 for values in the RiskFactor column, and (via debug) that #newEnvScore has a value of 2. I've also verified that my query has a row with code = 'RISK_LEVEL_ENVIRONMENTAL' and RiskFactor = 2.
I've verified via debug that failure is due to #newEnvRiskLevel staying at -1 and that #errorCode is 0.
I've also tried cast to both decimal and int, convert to int, and "rl.RiskFactor - #newEnvScore < 1" in my where clause, none of which set newEnvRiskLevel.
As I say, it's only when running this as a stored procedure that failure happens, which is the part I really don't understand. I'd expect SQL Server to be deterministic, whether the SQL is running the body of a stored procedure, or running the exact same SQL in a SSMS tab.
It is unfortunate that you do post neither your stored procedure nor a complete script. It is difficult to diagnose a problem without a useful demonstration. But I see the use of "goto" which is concerning in many ways. I also see the use of a select statement to assign a local variable - which is often a problem because the developer might be assuming an assignment always occurs. To demonstrate - with a bonus at the end
set nocount on;
declare #risk smallint;
declare #risklevels table (risklevel float primary key, code varchar(10));
insert #risklevels(risklevel, code) values (1, 'test'), (2, 'test'), (-5, 'test');
-- here is your assignment logic. Notice that #risk is
-- never changed because there are no matching rows.
set #risk = 0;
select #risk = risklevel from #risklevels where code = 'zork';
select #risk;
-- here is a better IMO way to make the assignment. Note that
-- #risk is set to NULL when there are no matching rows.
set #risk = -1;
set #risk = (select risklevel from #risklevels where code = 'zork');
select #risk;
-- and a last misconception. What value is #risk set to? and why?
set #risk = -1;
select #risk = risklevel from #risklevels where code = 'test';
select #risk;
Whether this is the source of your problem (or contributes to it) I can't say. But it is a possibility. And storing integers in a floating point datatype is just a problem generally. Even if you cannot change your table, you can change your local variables and force the use of a more appropriate datatype. So perhaps that is another change you should consider.

SQL Error : The multi-part identifier ... could not be bound

I'm currently stuck in this problem in SQL Server and couldn't figure out where the problem is.
I'm using stored procedure for the following code :
DECLARE #cSql nVARCHAR(1000)
SET #cSql = 'SELECT
[A].[REC_ID],
[A].[ADJUSTMENT_REC_ID],
[A].[ITEM_REC_ID],
[B].[CODE] [ITEM_CODE],
[B].[ALIAS_NAME] [ITEM_NAME],
[A].[WAREHOUSE_REC_ID],
[C].[CODE] [WAREHOUSE_CODE],
[C].[NAME] [WAREHOUSE_NAME],
[A].[qty_before_basic_uom],
[A].[qty_before_uom_1],
[A].[qty_adjust_basic_uom],
[A].[qty_adjust_uom_1],
[A].[qty_after_basic_uom],
[A].[qty_after_uom_1],
[A].[basic_uom],
[A].[uom_1],
[A].[ADJUST_VALUE],
[A].[cogs_adjust],
[A].[cogs_adjust_total],
[A].[asset_account_rec_id],
[A].[debit_account_rec_id],
[A].[credit_account_rec_id],
[A].[remark],
[A].[record_version],
[A].[void_status],
[A].[void_reason],
[A].[void_datetime],
[A].[void_user_rec_id],
[A].[create_datetime],
[A].[create_user_rec_id],
[A].[edit_datetime],
[A].[edit_user_rec_id],
[A].[delete_datetime],
[A].[delete_user_rec_id]
INTO [' + #cTemp + ']
FROM [IM_trsInventoryAdjustment_Detail] [A]
JOIN [IM_mstInventoryItem] [B] ON
[B].[REC_ID] = [A].[item_rec_id]
JOIN [IM_mstWarehouse] [C] ON
[C].[REC_ID] = [A].[warehouse_rec_id]
WHERE 1=0;'
EXEC sp_executeSQL #cSql
And as soon as I executed the query, SQL Server springs up "The multi-part identifier" error on every single column.
Could you help me locate where my mistake is, please??
P.S. I'm using dynamic query since the temporary table that I'm injecting the data to will keep on changing...
Holy, turns out the only problem is that my variable is not long enough to contain the whole command.
Here's the result when i replace EXEC with PRINT :
SELECT
[A].[REC_ID],
[A].[ADJUSTMENT_REC_ID],
[A].[ITEM_REC_ID],
[B].[CODE] [ITEM_CODE],
[B].[ALIAS_NAME] [ITEM_NAME],
[A].[WAREHOUSE_REC_ID],
[C].[CODE] [WAREHOUSE_CODE],
[C].[NAME] [WAREHOUSE_NAME],
[A].[qty_before_basic_uom],
[A].[qty_before_uom_1],
[A].[qty_adjust_basic_uom],
[A].[qty_adjust_uom_1],
[A].[qty_after_basic_uom],
[A].[qty_after_uom_1],
[A].[basic_uom],
[A].[uom_1],
[A].[ADJUST_VALUE],
[A].[cogs_adjust],
[A].[cogs_adjust_total],
[A].[asset_account_rec_id],
[A].[debit_account_rec_id],
[A].[credit_account_rec_id],
[A].[remark],
[A].[record_version],
[A].[void_status],
[A].[void_reason],
[A].[void_datet
So this is what i did. I changed :
DECLARE #cSQL NVARCHAR(1000)
to
DECLARE #cSQL NVARCHAR(4000)
and it works, big time. The error is gone, and I can continue to deal with another bugs now.
Thank for the comments and inputs!!

T-SQL Replace XML node

I would like to replace an XML node with a new node. I am trying to make this dynamic so the replacement node name is a variable
DECLARE #xmlSource AS XML = '<Root><Transactions><ReplaceMe>This information should be gone</ReplaceMe></Transactions></Root>'
DECLARE #xmlInsert AS XML = '<NewNode>New Information</NewNode>'
DECLARE #NodeName NVARCHAR(500) = 'ReplaceMe'
The resulting XML should look like:
<Root><Transactions><NewNode>New Information</NewNode></Transactions></Root>
There is no direct approach to replace a complete node with another one.
But you can delete it and insert the new one:
DECLARE #xmlSource AS XML = '<Root><Transactions><ReplaceMe>This information should be gone</ReplaceMe></Transactions></Root>'
DECLARE #xmlInsert AS XML = '<NewNode>New Information</NewNode>'
DECLARE #NodeName NVARCHAR(500) = 'ReplaceMe'
SET #xmlSource.modify('delete /Root/Transactions/*[local-name(.) eq sql:variable("#NodeName")]');
SELECT #xmlSource; --ReplaceMe is gone...
SET #xmlSource.modify('insert sql:variable("#xmlInsert") into (/Root/Transactions)[1]');
SELECT #xmlSource;
The result
<Root>
<Transactions>
<NewNode>New Information</NewNode>
</Transactions>
</Root>
UPDATE a generic solution
From your comments I understand, that you have no idea about the XML, just the need to replace one node where you know the name with another node...
This solution is string based (which is super ugly anyway) and has some flaws:
If there are several nodes with this name, only the first one will be taken
If the node exists multiple times with the same content, it would be replaced in both places
If your xml contains CDATA-sections they will be transfered into properly escaped normal XML implicitly. No semantic loss, but this could break structural validations...
This should work even with special characters, as all conversions are from XML to NVARCHAR and back. Escaped characters should stay the same on both sides.
Otherwise one had to use a recursive approach to get the full path to the node and build my first statement dynamically. This was cleaner but more heavy...
DECLARE #xmlSource AS XML = '<Root><Transactions><ReplaceMe>This information should be gone</ReplaceMe></Transactions></Root>'
DECLARE #xmlInsert AS XML = '<NewNode>New Information</NewNode>'
DECLARE #NodeName NVARCHAR(500) = 'ReplaceMe'
SELECT
CAST(
REPLACE(CAST(#xmlSource AS NVARCHAR(MAX))
,CAST(#xmlSource.query('//*[local-name(.) eq sql:variable("#NodeName")][1]') AS NVARCHAR(MAX))
,CAST(#xmlInsert AS NVARCHAR(MAX))
)
AS XML)
To replace in place with XML we'll need to insert our new nodes immediately before (or after) the nodes we want to replace.
Start off by getting the number of nodes we want to replace:
DECLARE #numToReplace int = #xmlSource.value('count(//*[local-name(.) eq sql:variable("#NodeName")])', 'int')
Then iterate through each node and flag the node to be deleted (this lets us replace the nodes with a node of the same name).
DECLARE #iterator int = #numToReplace
WHILE #iterator > 0
BEGIN
SET #xmlSource.modify('insert attribute ToDelete {"delete"} into ((//*[local-name(.) eq sql:variable("#NodeName")])[sql:variable("#iterator")])[1]');
SET #iterator = #iterator - 1
END
n.b. you need to nest the target query ((*query*)[sql:variable("#numToReplace")])[1], it doesn't like variables in the last node indexer
Then insert the new node before each old node
SET #iterator = #numToReplace
WHILE #iterator > 0
BEGIN
SET #xmlSource.modify('insert sql:variable("#xmlInsert") before ((//*[local-name(.) eq sql:variable("#NodeName")][#ToDelete="true"])[sql:variable("#iterator")])[1]')
SET #iterator = #iterator - 1;
END
Then you can just remove all the old nodes
SET #xmlSource.modify('delete (//*[local-name(.) eq sql:variable("#NodeName")][#ToDelete="true"])')

Resources