Querying Json array column and other current table column - sql-server

I have a table that has three columns from which I need to retrieve the data. One of the columns OtherNames contain an array of Json Objects.
CREATE TABLE Persons (
NameID int,
CurrentName varchar(255),
OtherNames varchar(max),
);
I can query that column just fine, but how can I join it with the table it is in by ID so I can retrieve all the information on the table and what is related to this row.
DECLARE #test VARCHAR(MAX)
SELECT #test = '[{"Name":"Bob","DateTime":"03/03/2022"},{"Name":"Adam","DateTime":"04/05/2022"}]'
SELECT * FROM OPENJSON(#test)
WITH (
Name VARCHAR(MAX) '$.Name',
DateTime VARCHAR(MAX) '$.DateTime'
)
This above results in
Bob 03/03/2022
Adam 04/05/2022
How can I join to show the NameID and CurrentName along with it ?
NameID Name DateTime CurrentName
1 Bob 03/03/2022 Rob
1 Adam 04/05/2022 Rob
There could be multiple records and multiple Json data..

As I mentioned in the comments, use OPENJSON against the column, not a scalar variable which contains the value of just one of your rows, and none of the other row data.
SELECT P.NameID,
ONs.[Name],
ONs.[DateTime],
P.CurrentName
FROM dbo.Persons P
CROSS APPLY OPENJSON(P.OtherNames)
WITH ([Name] varchar(255),
[DateTime] date) ONs;
Note that as your value [DateTime] is culture dependant, you may need to define it as a varchar(10) in the WITH, and then CONVERT it to a date in the SELECT with a style code.

Related

How do you process xml columns and check every xml entries with MSSQL?

<Standard>
<Equip Cat="Hardware">10 TB Disk</Equip>
<Equip Cat="Hardware">USB 2.0</Equip>
</Standard>
I have a column called XML in a table called Product. The type is XML(.), and I am wondering how I can process the xml column.
The big issue is that I have no idea how to do a foreach in a XML column.
I want to add a row if my stored procedure detects the substring "10 TB" inside of the category "Hardware"inside the table called ProductFeature with the id from table Product in the column id and true inside of the column HighDiskSpace.
Here is a conceptual example for you.
It is using XQuery .exist() method. Its XPath predicate expression satisfies your question requirements. Both variables, #cat and #searchString, could be your stored procedure parameters.
SQL
-- DDL and sample data population, start
DECLARE #Product TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO #Product (xmldata) VALUES
(N'<Standard>
<Equip Cat="Hardware">10 TB Disk</Equip>
<Equip Cat="Hardware">USB 2.0</Equip>
</Standard>');
-- DDL and sample data population, end
DECLARE #cat VARCHAR(30) = 'Hardware'
, #searchString VARCHAR(30) = '10 TB';
SELECT *
FROM #Product
WHERE xmldata.exist('(/Standard/Equip[#Cat=sql:variable("#cat")
and contains(./text()[1], sql:variable("#searchString"))])[1]') = 1;

Getting ID into temp table variable on INSERT INTO ... OUTPUT ... INTO temp table

This is the sample procedure I am using.
create procedure PRO_ProcName
#description varchar(max),
#txn_no varchar
as
begin
declare #txn table (
id bigint,
description varchar(max),
txn_no varchar
);
declare #txn_id bigint;
insert into transactions
(
description,
txn_no
)
output
inserted.description,
inserted.txn_no
into #txn
values
(
#description,
#txn_no
)
select #txn_id = id from #txn;
end
I am getting an error like:
Column name or number of supplied values does not match table definition.
I know that it is because I have id field in my temporary table and it is not getting inserted in the insert into statement. I cannot give value for id because it is the auto increment primary key.
How can I tackle this situation and get id of inserted record into a variable?
The inserted table represents the data that exists in the target table after the insert - so it also includes the auto-generated values, whether they where generated by a default value definition or by an identity definition on the columns - so you need to add inserted.id to the output clause.
However, there are two more things wrong in your procedure.
The first and most important is the fact that you didn't specify a length to the #txn_no varchar parameter. SQL Server will implicitly specify the length of 1 char in this case.
The second is the fact that you are not specifying the columns list of #txn in the output clause.
Here is a improved version of your code with all these issues fixed:
create procedure PRO_ProcName
#description varchar(max),
#txn_no varchar(255) -- Note: I don't know the actual length you need
as
begin
declare #txn table (
id bigint,
description varchar(max),
txn_no varchar
);
declare #txn_id bigint;
insert into transactions
(
description,
txn_no
)
output
inserted.id,
inserted.description,
inserted.txn_no
into #txn(id, description, txn_no)
values
(
#description,
#txn_no
)
select #txn_id = id from #txn;
end
I cannot give value for id because it is the auto increment primary key.
No it isn't. You haven't declared it to be anything of the sort. So we need to fix that first:
declare #txn table (
id bigint IDENTITY PRIMARY KEY,
description varchar(max),
txn_no varchar
);
And then we fix it by specifying a column list in your INTO clause:
output
inserted.description,
inserted.txn_no
into #txn (description, txn_no)
It's always a good habit to specify column lists anyway.
Or if I've misinterpreted your question, and the id should be coming from transactions, then you just add inserted.id as another column in your OUTPUT clause. inserted represents that state of the table after the insert. So you can include columns from it in your OUTPUT clause even if you didn't specify them in the INSERT.

Get more than 1 id to new inserted row

I have this data.
I want to duplicate data like a picture above with stored procedure.
First thing I do is copying two rows in the first table. How can I get 2 (two) 'iId' in the first table to create 2 (two) rows in the second table and put those 'iId' into 'iId_JTS-Rule_RulePricingGroup' like the picture above?
I think you can use OUTPUT clause with INSERT
CREATE TABLE #Table1(
ID int IDENTITY PRIMARY KEY,
Title varchar(10)
)
CREATE TABLE #Table2(
ID int,
Title varchar(10)
)
DECLARE #NewIDs TABLE(ID int)
INSERT #Table1(Title)
OUTPUT inserted.ID INTO #NewIDs(ID) -- save new IDs
VALUES ('A'),('B'),('C')
INSERT #Table2(ID,Title)
SELECT ID,Title
FROM #Table1
WHERE ID IN(SELECT ID FROM #NewIDs) -- use new IDs
DROP TABLE #Table1
DROP TABLE #Table2

T-SQL - Validate BLOB / varbinary(max) data

Data is being migrated from Table A to Table B.
Table A has 2 columns - an identity column and a column Content defined as varbinary(max).
How can I validate that Table B has been loaded with correct data for Content column? Is T_SQL's EXCEPT operator good enough? Are there alternate methods?
Thanks
EXCEPT is the tool for this job. Note that unlike other SQL Server set operators, the order makes a difference. Here's one way to validate using EXCEPT:
-- sample data
DECLARE #table1 TABLE (id int identity, content varbinary(max));
DECLARE #table2 TABLE (id int identity, content varbinary(max));
INSERT #table1(content) VALUES (12), (15), (20);
INSERT #table2(content)
SELECT content
FROM #table1;
--solution
(
SELECT id, content FROM #table1
EXCEPT
SELECT id, content FROM #table2
)
UNION ALL
(
SELECT id, content FROM #table2
EXCEPT
SELECT id, content FROM #table1
);

How can I split the contents of my table into two tables with an index?

I have a SQL Server table with the schema
varchar type,
varchar id,
int date,
varchar(MAX) data
And I want to split the data column into its own table and give it a unique index that I would put in my existing table (altered to accept an int instead of varchar(max) for data)
How can I select all of the rows and insert the data column into one table, then take the newly created auto_incremented id and insert the rest of the columns into another table with the auto_incremented id as the new 4th column?
Move the table to new temp table with Identity column. from that table, first create your new data table, then again create your second table.
declare #OriginalTable (type varchar, id Varcher,date int, data varchar(MAX))
declare #TempTable (Ident int identity(1,1), type varchar, id archer,date int, data varchar(MAX))
insert into #TempTable (type, id, date, data) select * from # OriginalTable
-- Create the Split tables
select ident, type, id, date into #Table1 From #TempTable
select ident, data into #Table2 From #TempTable

Resources