Attempting To Modify XML in SQL Server Using XQuery - sql-server

I am attempting to add an attribute to a node in an XML column in SQL Server.
UPDATE
TableName
SET Metadata.modify('
insert attribute MyAttribute{"01b9cd0b-bfed-436f-bc58-57d2fddd9211"}
into (Root/Collection/Item[#No="360"][1])
')
WHERE
TableName.Id = 1
I get the following error...
Msg 2226, Level 16, State 1, Line 4 XQuery
[TableName.Metadata.modify()]: The target of 'insert' must be a single
node, found 'element(Item,xdt:untyped) *'
But I thought my selection would return a single item, given the [1]

Stupid XQuery! (Or possibly me).
You need to place the [1] outside of the brackets:
into (Root/Collection/Item[#No="360"][1])
Should be
into (Root/Collection/Item[#No="360"])[1]

Related

XML parsing: line 1, character 345, duplicate attribute

I am trying to get the particular attribute value from XML column, but I'm getting an error
XML parsing: line 1, character 345, duplicate attribute
My code:
select
ship_to_cust_num,
tank_num,
tank_capacity_qty,
tank_pkg_type_code,
COALESCE(REPLACE(CAST(CAST(b.tank_inspection AS NTEXT) AS XML).value('(/TankInspection/Questions/Question[#AASAQno="9"]/#QAns)[1]', 'VARCHAR(50)'), '#', ''), 0)
from
bulk_site_tank (nolock)b
where
convert(varchar, b.tank_inspection) != 'NULL'
The simple answer is that the error is telling you the problem. But to explain further. Take this simple statement:
DECLARE #xml varchar(MAX);
SET #XML = '
<root>
<child>
<element attribute="1">value</element>
<element attribute="2" attribute="2">Another Value</element>
</child>
</root>';
SELECT *
FROM (VALUES(CONVERT(xml, #XML)))V(X);
If you run that, you'll get the error:
Msg 9437, Level 16, State 1, Line 11 XML parsing: line 5, character 46, duplicate attribute
Unsurprising, as if you look, the second element node has attribute declared twice.
So, how do you fix this?
Firstly, this means that you're storing your XML data as a datatype other than in an xml data type. XML should be stored using the xml data type (that's exactly what it's for), and only valid XML can be stored in it; as a result you wouldn't have been able to insert invalid XML into the row and wouldn't be in this position. As you are, there's only one thing you can do; find all the "bad" rows:
SELECT tank_inspection
FROM bulk_site_tank
WHERE TRY_CONVERT(xml,tank_inspection) IS NULL
AND tank_inspection IS NOT NULL;
Then inspect every single row returned in the above dataset and fix the data. Make it valid XML. After that, fix your data type:
ALTER TABLE bulk_site_tank ALTER COLUMN tank_inspection xml;
Now everything is valid XML, you can fix that query of yours:
SELECT ship_to_cust_num,
tank_num,
tank_capacity_qty,
tank_pkg_type_code,
REPLACE(b.tank_inspection.value('(/TankInspection/Questions/Question[#AASAQno="9"]/#QAns)[1]', 'varchar(50)'), '#', '') --AS ?
FROM bulk_site_tank b
WHERE b.tank_inspection IS NOT NULL;
Note I change to ANSI_NULL syntax, and got rid of the NOLOCK (as I assume you don't know what it actually does here). The CAST/CONVERT expressions are gone too, and I've removed the COALESCE. As your value expression returns a varchar(50) and the COALESCE has a 0 for the second parameter. This would implicitly cast the value returned from the XML to an int and likely result in a conversion error.
I'm afraid it's up to you to clean up your data though, no one else can help you here I'm afraid. This is just one reason why poor data type choices is a problem; as if the correct data type was used then,as I said before, the invalid XML could never have been inserted.
Good luck!

How to create schema binding and index on view from other server?

I have tried creating a view with the help of schema binding and indexing which is referring from other server table. But sql thrown some error for the below query .
create VIEW [dbo].[Vxyz]
with schemabinding
AS
SELECT
ELID,USECOUNT,LASTUPDATE,TYPE,CODENE,CASNUE,NAME_ENG,ISGROUP,CHGROUP,DLink
IDE,LOCKBY,PhyApB,BUILDNO,PMNNumE,EINECE
FROM IADL.dbo.tblxyz
GO
create unique clustered index IDX_xyz on [dbo].
[Vxyz](ELID)
Found below error
Msg 4512, Level 16, State 3, Procedure IADL.dbo.tblxyz, Line 3 [Batch Start Line 11]
Cannot schema bind view '[dbo].[Vxyz]' because name 'IADL.dbo.tblxyz' is invalid for schema binding. Names must be in two-part format
and an object cannot reference itself.
Msg 1939, Level 16, State 1, Line 17
Cannot create index on view '[dbo].[Vxyz]' because the view is not schema bound.
select distinct
ISNULL(A.elid, B.elid) ElementID,
CASE when A.elid is null and B.elid is not null then 'Missing ElementID :'+
B.elid+' in Mainproductsall table' when A.elid is not null
and B.elid is null then 'Missing ElementID :'+ A.elid+' in Genproductsall table' Else 'OK'
end Datastatus
into ABC
from [dbo].[Vxyz] As A
full outer join [dbo].[Vxyzwa] as B on A.elid = B.elid
where A.elid is null or B.elid is null
Each from from above query is view . As per my first query above which is referring from other server. so i want to optimize and i am trying to create index.
If you check official documentation, you will see that it is stated as follows
All referenced objects must be in the same database.
So you cannot refer a base table from an other database.
This means, for all referenced current database objects should be referenced with their schema name and object name.

Issues with SQL Server functions and triggers

I have been working on this project by using "advanced" features of SQL Server and creating functions, triggers, but two of these are giving me serious issues.
I am supposed to create a function that includes one input parameter and returns a table. The function itself will return a summary of the individual costs of each insurance expense (base, spouse, etc.), a total of those expenses and the employees name given the number of dependents a given employee has- the user enters the number of dependents as an input parameter.
CREATE FUNCTION fnInsCosts
(#NoDependants int)
--returns table datatype
RETURNS table
AS
--Set the Return to select the columns and aggregated columns from vwPayRoll as listed in exercise 3 of Module 12 --assignment sheet where Dependants is = to the input variable.
RETURN (SELECT
EmpName,
SUM(BaseCost) AS TotBaseCost, SUM(SpouseIns) AS TotSpouseCost,
SUM(DepIns) AS TotDepCost, SUM(DentalCost) AS TotDentalCost,
SUM(BaseCost * SpouseIns * DepIns * DentalCost) AS TotInsCost
FROM
vwPayroll
WHERE
Dependants = #NoDependants
GROUP BY
Dependants);
SELECT * FROM dbo.fnInsCosts(2);
SELECT * FROM dbo.fnInsCosts(0);-- Unfinished/error with select and EmpName?
Here is the error I get when I try to run the whole thing:
Msg 156, Level 15, State 1, Procedure fnInsCosts, Line 15
Incorrect syntax near the keyword 'SELECT'.
And it says this when I run everything except for the part where I invoke it:
Msg 8120, Level 16, State 1, Procedure fnInsCosts, Line 10
Column 'vwPayroll.EmpName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
And here is the last one; I am creating a trigger and I need to create two table copies:
--Test for the existence of a fake table named TempEmpData. If it exists, drop it.
IF OBJECT ID('TempEmpData') IS NOT NULL
DROP TABLE TempEmpData;
--Test for the existence of a fake table named TempWork. If it exists, drop it.
IF OBJECT ID('TempWork') IS NOT NULL
DROP TABLE TempWork;
--Select everything from EmpData into the appropriate fake table
SELECT * INTO TempEmpData FROM EmpData
--Select everything from Work into the appropriate fake table
SELECT * INTO TempWork FROM Work
GO
CREATE TRIGGER TempEmpDate_INSERT_UPDATE_DELETE
ON TempEmpData
AFTER INSERT, UPDATE, DELETE
AS
--(USE THIS CONDITIONAL STRUCTURE- substitute variable names where needed and remove the "--")
IF EXISTS (SELECT * FROM Deleted JOIN TempEmpData ON Deleted.EmpID = TempEmpData.EmpID)
--the correct primary key)
BEGIN;
--Custom error message
THROW 11, 'EmpID is in use; transaction cancelled!', 1;
--rollback the transaction
ROLLBACK TRAN;
END;
ELSE
BEGIN
--Update the appropriate fake table
CREATE TRIGGER TempEmpData_INSERT_UPDATE
ON TempEmpData
AS
--Set the appropriate column to the correct value
--Where the correct primary key is in a subquery selecting that same key from the
--system table that handles inserts
UPDATE TempEmpData
SET BenPlanID = 0;
DELETE TempEmpData
WHERE EmpID = 41;
INSERT TempEmpData
VALUES ('Bill', 'Smith', '11/14/2014', 0, 0, 1, NULL, 2);
SELECT *
FROM TempEmpData
ORDER BY EmpID DESC
END;
And here are the errors:
Msg 4145, Level 15, State 1, Line 4
An expression of non-boolean type specified in a context where a condition is expected, near 'ID'.
Msg 4145, Level 15, State 1, Line 8
An expression of non-boolean type specified in a context where a condition is expected, near 'ID'.
Msg 156, Level 15, State 1, Procedure TempEmpDate_INSERT_UPDATE_DELETE, Line 17
Incorrect syntax near the keyword 'TRIGGER'.
I would be extremely grateful for any insight.
You are using the "new" inline syntax to create a function, great!
The first error comes from the missing "GO" to separate the creation of your function from the call to it
CREATE FUNCTION fnInsCosts()
--You function code here
GO
SELECT * FROM dbo.fnInsCosts(2);
The second error in your function has its reason - as stated by JamesZ already - in the wrong grouping column:
SELECT EmpName,
SUM(BaseCost) AS TotBaseCost,
SUM(SpouseIns) AS TotSpouseCost,
SUM(DepIns) AS TotDepCost,
SUM(DentalCost) AS TotDentalCost,
SUM(BaseCost * SpouseIns * DepIns * DentalCost) AS TotInsCost
FROM vwPayroll
WHERE Dependants = #NoDependants
GROUP BY EmpName
You see, that the only column which has not got any aggregation function is the EmpName...
And the last one - again stated by JamesZ already is the missing underscore in the function's name OBJECT ID:
IF OBJECT_ID('TempEmpData') IS NOT NULL
In your code T-SQL is searching for the meaning of "object" and for a function called "ID"... (The same with IF OBJECT ID('TempWork') IS NOT NULL)
And one last point: On SO it is highly advised to create one question per issue. This question should've been at least parted in two separate questions. Just think of future readers searching for similar problems...
EDIT Ups, there was even one more...
Your last error message points to some code where I do not understand what you really want to achieve... Are you creating a trigger from within the trigger? Might be, the MERGE statement was the better approach for your needs anyway...

Query error with Ambiguous column name

When executing the following SQL query on Microsoft SQL Server 2008 :
SELECT
[ACCOUNT]
,[Mailto]
,[Site_addr_1]
,[Site_addr_2]
,[Site_addr_3]
,[State_Class]
,[Map_Facet]
,[Key_Map]
,[Neighborhood_Code]
,[Neighborhood_Group]
,[Econ_Area]
,[Yr_Impr]
,[Acreage]
,[Prior_Total_Market_Value]
,[Land_Value]
,[Improvement_Value]
,[Extra_features_Value]
,[Total_Appraised_Value]
,[Total_Building_Area]
,[Econ_Bld_Class]
,[LAND_USE_CODE]
FROM [Pdata].[dbo].[Real_acct]
LEFT JOIN [Pdata].[dbo].[Land]
ON (Real_acct.ACCOUNT = LAND.ACCOUNT)
I get the following error:
Msg 209, Level 16, State 1, Line 1
Ambiguous column name 'ACCOUNT'.
You are doing a join and it seems that both tables have the column ACCOUNT and sql server doesn't know if you want the column ACCOUNT from Real_acct or Land.
Try this:
SELECT
Real_acct.ACCOUNT -- or Land.ACCOUNT
,Mailto
,Site_addr_1
,Site_addr_2
,Site_addr_3
,State_Class
,Map_Facet
,Key_Map
,Neighborhood_Code
,Neighborhood_Group
,Econ_Area
,Yr_Impr
,Acreage
,Prior_Total_Market_Value
,Land_Value
,Improvement_Value
,Extra_features_Value
,Total_Appraised_Value
,Total_Building_Area
,Econ_Bld_Class
,LAND_USE_CODE
FROM [Pdata].[dbo].[Real_acct]
LEFT JOIN [Pdata].[dbo].[Land]
ON (Real_acct.ACCOUNT = LAND.ACCOUNT)
The very first column... the server doesn't know if you want Real_acct.ACCOUNT or LAND.ACCOUNT
#majidarif is completely correct.
The reason is that both tables have a column named "Account".
You need to specify which table you want the value returned from.
Even if they are the same you need to be specific.

Error in SQL Server updating Image datatype from a linked server

This is a table in a Microft Dynamics 2009 database. Our Test database is missing a bunch of Image data, so I would like to update the table in test with the data in production. I'm using this SQL for this update. When I execute this, I get this error:
Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 306, Level 16, State 2, Line 1
The text, ntext, and image data types cannot be compared or sorted, except when using IS NULL or LIKE operator.
Query:
UPDATE INVENTTABLE
SET
Z_IMAGE = i2.Z_IMAGE,
Z_IMAGEMIMETYPE = i2.Z_IMAGEMIMETYPE
FROM INVENTTABLE i1
JOIN [PRODSQLSERVER].[DAX2009DB].[dbo].INVENTTABLE i2
ON i1.RECID = i2.RECID
WHERE i2.Z_IMAGE IS NOT NULL
I can't see a place where I'm attempting to compare or sort the Image data.
Try changing UPDATE INVENTTABLE to UPDATE i1.

Resources