I hope it's plain to see what I want to accomplish here. I've been experimenting a little back and forth.
insert into #description
select
d.value('*[1]', 'varchar(MAX)') text
,d.value('../#id', 'varchar(50)') parent
from #xml.nodes('//*[local-name(.)="description"]') as xtbl(d)
I want to query all the elements of name description, record the inner text and a reference to the parent node.
The above runs but text is all NULL. (Edit)
XML exerpt:
<effort id="6d9cb0d1-58b0-11e2-acbb-00268315c2c5" start="2013-01-07 10:55:55" status="1" stop="2013-01-07 11:10:34">
<description>
Stängde sajten med felmeddelande.
</description>
</effort>
Table def:
declare #description table(
text varchar(MAX)
,parent varchar(50)
)
Thanks!
Related
I noticed that there is different output for this
SELECT id,name,description FROM table_name;
as opposed to this
SELECT (id,name,description) FROM table_name;
Is there any big difference between the two?
What is the purpose of this?
create table table_name(id int, name text, description text);
insert into table_name
values (1, 'John', 'big one');
select (id, name, description), id, name, description
from table_name;
row | id | name | description
--------------------+----+------+-------------
(1,John,"big one") | 1 | John | big one
(1 row)
The difference is important. Columns enclosed in parenthesis form a row constructor known also as a composite value, returned in a single column. Usually, separate columns are preferred as a query result. Row constructors are necessary when a row as a whole is needed (e.g. in the VALUES of the above INSERT command). They are also used as values of composite types.
The following query actually is selecting a ROW type value:
SELECT (id, name, description) FROM table_name;
This syntax by itself would not be very useful, and more typically you would use this if you were doing an INSERT INTO ... SELECT into a table which had a row type in its definition. Here is an example of how you might use this.
CREATE TYPE your_type AS (
id INTEGER,
name VARCHAR,
description VARCHAR
);
CREATE TABLE your_table (
id INTEGER,
t your_type
);
INSERT INTO your_table (id, t)
SELECT 1, (id, name, description)
FROM table_name;
From the Postgres documentation on composite types:
Whenever you create a table, a composite type is also automatically created, with the same name as the table, to represent the table's row type.
So you have already been working with row types, whether or not you knew it.
So this is weird issue that is related to only one letter: ț I'm talking about Microsoft SQL Server and database that has Collation property set to Romanian_CI_AS.
When I launch this query:
select name from mytable where id = 1
I'm getting correct result containing this special character. But when I'm launching this query:
declare #name varchar(max) = (select name from mytable where id = 1)
select #name
or this one:
declare #name varchar(max) = (select name COLLATE Romanian_CI_AS from mytable where id = 1)
select #name
I'm seeing ? instead of this particular letter. Any other special characters work fine.
Do you know how can I assign this value to a variable without loosing mentioned letter?
I have seen similar posts on this but have not found my exact issue and an answer. What I am trying to do is update a table with data from a variables and from data from a select statement.
For instance:
--THESE ARE THE VARIABLES I WANT TO USE IN INSERT
DECLARE #Key uniqueidentifier
DECLARE #Name varchar(200)
SET #Key = NEWID()
SET #Name = 'TestName'
--THIS IS A TEMP TABLE THAT I WANT TO SELECT FROM AND USE THE DATA FROM THERE AND INSERT
SELECT * FROM #TempData AS td
--THE INSERT STATEMENT
INSERT INTO MyTable(CustomerKey, Name, City, State)
VALUES(#Key, #Name, td.City, td.State)
Now for the SELECT statement, I was going to use variables for the column names like:
SELECT #City = City, #State = State FROM #TempData
But the only problem, or rather annoying is that the actual temp table has easily 40 columns in it. I really don't want to declare 40+ variables and assign it to each column.
Any thoughts on how this could be done?
What about just simply doing..
INSERT INTO MyTable(CustomerKey, Name, City, State)
SELECT #Key, #Name, City, State FROM #TempData
WHERE ....
Basically you can scale this out for any number of columns in TempData and not have to declare variables for it.
I have a table and initially it has one entry as follows
ID ParentID Title
1 NULL All
This table I am using to create tree structures. The table needs to be filled with the following data stored in CSV file. Each line represents one tree path
All;World
All;World;NA
All;World;NA;Canada //Here each item represents the tree node and separated by ;
--
--
I am looking to write a query which will take input like All;World;NA and create entry in table if does not exist and return the ID of the created entry or an existing entry. So in my example with input All;World;NA the table should look like this after query is run
ID ParentID Title
1 NULL All
2 1 World
3 2 NA
and it has created 2 entries and ID=3 returned since path All;World;NA represents ID=3
If I give another input like All;World;NA;Canada, then it will create one more entry and ID=4 returned.
If I re-run query with input All;World;NA;Canada then it will find that entry exists and return ID=4
Can anyone help?
Here is something you can start with:
CREATE TABLE TREE
(
ID INT NOT NULL IDENTITY(1,1),
ParentID INT,
Name varchar(32)
);
GO
CREATE PROC InsertIntoTree #node varchar(512)
AS
BEGIN
DECLARE #xml xml,#str varchar(100),#delimiter varchar(10)
SET #delimiter =';'
SET #xml = cast(('<X>'+replace(#node,#delimiter ,'</X><X>')+'</X>') as xml)
DECLARE #nodes TABLE (NodeName varchar(32));
INSERT INTO #nodes(NodeName)
SELECT C.value('.', 'varchar(10)') as NodeName FROM #xml.nodes('X') as X(C)
DECLARE #nodename varchar(32)
DECLARE #nodeid int
DECLARE #parentNodeId int
SET #parentNodeId = null
SELECT TOP 1 #nodename=Nodename from #nodes
WHILE (##ROWCOUNT <> 0 and #nodename IS NOT NULL)
BEGIN
SET #nodeid = null
SELECT #nodeid=Id FROM TREE WHERE Name=#nodename
IF(#nodeid is null )
BEGIN
INSERT INTO TREE(ParentID,Name) VALUES(#parentNodeId,#nodename)
SET #nodeid = ##IDENTITY
END
SET #parentNodeId = #nodeid
delete from #nodes where NodeName=#nodename
SELECT TOP 1 #nodename=Nodename from #nodes
END
END
GO
To test it:
InsertIntoTree 'A;B;C'
select * from tree
I leave it to the ready to optimize.
The name of a temporary table such as #t1 can be determined using
select #TableName = [Name]
from tempdb.sys.tables
where [Object_ID] = object_id('tempDB.dbo.#t1')
How can I find the name of a table valued variable, i.e. one declared by
declare #t2 as table (a int)
the purpose is to be able to get meta-information about the table, using something like
select #Headers = dbo.Concatenate('[' + c.[Name] + ']')
from sys.all_columns c
inner join sys.tables t
on c.object_id = t.object_id
where t.name = #TableName
although for temp tables you have to look in tempdb.sys.tables instead of sys.tables. where do you look for table valued variables?
I realize now that I can't do what I wanted to do, which is write a generic function for formatting table valued variables into html tables. For starters, in sql server 2005 you can't pass table valued parameters:
http://www.sqlteam.com/article/sql-server-2008-table-valued-parameters
moreover, in sql server 2008, the parameters have to be strongly typed, so you will always know the number and type of columns.
Table variable metadata is viewable in tempdb.sys.tables too. This is easily verifiable from the below
declare #t2 as table ( [38F055D8-25D9-4AA6-9571-F436FE] int)
SELECT t.name, t.object_id
FROM tempdb.sys.tables t
JOIN tempdb.sys.columns c
ON t.object_id = c.object_id
WHERE c.name = '38F055D8-25D9-4AA6-9571-F436FE'
Example Results
name object_id
------------------------------ -----------
#4DB4832C 1303675692
But you will notice the object name is auto generated and bears no relation to the variable name.
If you do not have a guaranteed unique column name that you can use to filter on as above and the table variable has at least one row in it you can (from SQL Server 2008 onwards) use %%physloc%% and DBCC PAGE to determine this information. Example below.
DECLARE #t2 AS TABLE ( a INT)
INSERT INTO #t2
VALUES (1)
DECLARE #DynSQL NVARCHAR(100)
SELECT TOP (1) #DynSQL = 'DBCC PAGE(2,' + CAST(file_id AS VARCHAR) + ',' +
CAST( page_id AS VARCHAR) +
',1) WITH TABLERESULTS'
FROM #t2
CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )
DECLARE #DBCCPage TABLE (
[ParentObject] [VARCHAR](100) NULL,
[Object] [VARCHAR](100) NULL,
[Field] [VARCHAR](100) NULL,
[VALUE] [VARCHAR](100) NULL )
INSERT INTO #DBCCPage
EXEC (#DynSQL)
SELECT VALUE AS object_id,
OBJECT_NAME(VALUE, 2) AS object_name
FROM #DBCCPage
WHERE Field = 'Metadata: ObjectId'
From Books Online:
A table variable behaves like a local variable. It has a well-defined scope, which is the function, stored procedure, or batch in which it is declared.
Given this, there should be no need to look up this value at run-time because you have to know it at design-time.
I don't believe you can, as table variables are created in memory not in tempdb.
On the topic of passing arbitrary lists/arrays into a SQL Server 2005 function or sproc, the least hokey way I know is to use an XML variable. If desired, that XML variable can be a strongly typed XML type that is associated w/ an XML Schema.
Given a list passed into a procedure/function as XML, you can extract that list into a table variable or temp table via "shredding".
"To shred" XML means to transform in the opposite direction--from XML to rowset(s). (The FOR XML clause causes a rowset to XML transformation.)
In the user-defined table function
CREATE FUNCTION [dbo].[udtShredXmlInputBondIdList]
(
-- Add the parameters for the function here
#xmlInputBondIdList xml
)
RETURNS
#tblResults TABLE
(
-- Add the column definitions for the TABLE variable here
BondId int
)
AS
BEGIN
-- Should add a schema validation for #xmlInputIssuerIdList here
--Place validation here
-- Fill the table variable with the rows for your result set
INSERT #tblResults
SELECT
nref.value('.', 'int') as BondId
FROM
#xmlInputBondIdList.nodes('//BondID') as R(nref)
RETURN
END
if the #xmlInputBondIdList is an XML fragment of the expected structure like that immediately below and is invoked as follows
DECLARE #xmlInputBondIdList xml
SET #xmlInputBondIdList =
'<XmlInputBondIdList>
<BondID>8681</BondID>
<BondID>8680</BondID>
<BondID>8684</BondID>
</XmlInputBondIdList>
'
SELECT *
FROM [CorporateBond].[dbo].[udtShredXmlInputBondIdList]
(#xmlInputBondIdList)
the result will be the rowset
BondId
8681
8680
8684
A couple other examples can be found at http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=678284&SiteID=1