Tsql Inserting Unordered Sequence - sql

I'm trying to insert an unordered sequence (list) into 2 kind of table explained here:
Table has one INT column
Table has several columns, one of them is an INT column (which I will use to insert the data)
So, here is the example;
List; (1, 3, 55, 3, 56456, 45)
Table; (Value INT)
I'm not looking for any solution, but a solution which is not including 'parse, split etc.' operations.
Expected solution:
INSERT INTO Table(Value)
VALUES(anyList)
Expected solution 2:
INSERT INTO Table(Value)
VALUELIST(anyList)
OR
INSERT INTO Table(Value)
VALUETABLE(anyList)

You can't directly insert like following.
INSERT INTO Table(Value)
VALUES (1, 3, 55, 3, 56456, 45)
You will get following error.
Msg 110, Level 15, State 1, Line 1 There are fewer columns in the
INSERT statement than values specified in the VALUES clause. The
number of values in the VALUES clause must match the number of columns
specified in the INSERT statement.
SQL Server will only accept your Insert if you give like following.
INSERT INTO Table(Value)
VALUES (1),(3),(55), (3), (56456), (45)
If you are getting the list as a string, in that case you need to convert it into appropriate format before inserting, like following.
DECLARE #xml as xml
DECLARE #list as varchar(max)
SET #list='(1, 3, 55, 3, 56456, 45)'
set #list = REPLACE(REPLACE(#list,'(',''),')','')
SET #xml = cast(('<X>'+replace(#list,',' ,'</X><X>')+'</X>') as xml)
INSERT INTO [Table](Value)
SELECT N.value('.', 'int') as value FROM #xml.nodes('X') as T(N)

Related

Create a procedure to insert multiple values into a table, using a single variable

Goal: To create a procedure to insert multiple values into a table, using a single variable.
Challenge: Instead of making multiple hits in the same table, I have created a single variable (#SQL) and stored multiple columns (fm_id and shdl_id ) results in it but I am unable to use this single variable in the insert statement.
Code:
create proc abc
(
#org_id numeric(10,0),
#shdl_id numeric(10,0),
#usr_id numeric(10,0),
#tst_id numeric(10,0)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #SQL NUMERIC(10);
SET #SQL= (SELECT fm_id,#shdl_id FROM [dbo].[students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id)
INSERT INTO [USER]
SELECT org_id,#usr_id,TST_ID,login_name,#SQL FROM [students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id
END
GO
Error :
Msg 213, Level 16, State 1, Procedure abc, Line 14 [Batch Start Line
94] Column name or number of supplied values does not match table
definition.
First you need to make your SELECT return only one value into the variable. There's no point selecting #shdl_id because you already know it?
DECLARE #pFMID NUMERIC(10);
SELECT #pFMID = MAX(fm_id) FROM [dbo].[students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id);
Then because you're not inserting a value into every column in the user table you need to explicitly state which columns to fill. Replace x1..x5 below with real column names (in the order the SELECT has them)
INSERT INTO [USER](x1,x2,x3,x4,x5)
-- ^^^^^^^^^^^^^^^
-- REPLACE THESE WITH REAL NAME
SELECT org_id,#usr_id,TST_ID,login_name,#pFMID FROM [students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id
END
GO
And as Uueerdo pointed out, this first query is a bit of a waste of time, we can write this:
create proc abc
(
...
)
AS
BEGIN
INSERT INTO [USER](x1,x2,x3,x4,x5)
SELECT org_id,#usr_id,TST_ID,login_name,fm_id FROM [students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id
-- ^^^^^
-- look!
You can only get away with leaving the column list off an INSERT if you're inserting the same number of columns the table has:
CREATE TABLE x(col1 INT, col2 INT);
INSERT INTO x VALUES (1,2) -- works
INSERT INTO x VALUES (1) -- fails: which column should have the 1?
INSERT INTO x(col1) VALUES (1) -- works: col1 shall have the 1

Convert function SQL Server

I'm trying to convert the data of a column from varchar(255) to Timestamp.
I went to Microsoft documentation and it's not working
Code:
SELECT
["Data Nascimento"]
FROM
[leoninos] AS Original,
CONVERT(VARCHAR, ["Data Nascimento"]) AS VARCHAR,
CONVERT(timestamp(6, 4), ["Data Nascimento"]) AS timestamp;
Error:
Msg 156, Level 15, State 1, Line 53.
Incorrect syntax next to keyword 'CONVERT'.
What is the syntax error?
Thanks in advance.
Don't use varchar and timestamp as column aliases. Try this:
SELECT ["Data Nascimento"] as original
TRY_CONVERT(varchar(255), ["Data Nascimento"]) AS type_varchar
-- TRY_CONVERT(timestamp(6, 4), ["Data Nascimento"]) AS type_timestamp
FROM [leoninos] ;
Notes:
timestamp isn't really appropriate. I don't know what you are trying to do.
The FROM clause goes after the SELECT list.
Don't use SQL keywords as column names (even if they are not reserved).
Use try_convert() in case the conversion fails.
It's hard to tell what you are doing- but it appears that you are trying to select a table and also two scalars at once. Try just doing the CONVERT statements on their own with sample values:
SELECT CONVERT(int, '10'), CONVERT(date, '20180720')
Then, once you have it working for some sample values, you can convert column values:
CREATE TABLE #test (a NVARCHAR(max))
INSERT INTO #test VALUES ('january 1 2018')
INSERT INTO #test VALUES ('20180720')
SELECT a, CONVERT(date, a) FROM #test
DROP TABLE #test

SELECT with comma separation in column

--Create/Populate [#Filters]:
if object_id('tempdb..[#Filters]','U') is not null drop table [#Filters]
go
create table [#Filters]
(
[filterid] int
,[filtertype] varchar(50)
,[filtername] varchar(50)
,[filtercriteria] nvcarchar(max)
)
go
set nocount on
insert [#Filters] select 1, 'Worklist', 'WL1', 'ID_SlotAssignmentFolder=1'
insert [#Filters] select 2, 'Worklist', 'WL2', 'ID_SlotAssignmentFolder=2'
insert [#Filters] select 3, 'Worklist', 'WL3', 'ID_SlotAssignmentFolder=3'
insert [#Filters] select 4, 'Filter', 'Filter1', 'filter_after_hours_offset=0,time_of_day_begin=00:00,worklistKey=1'
insert [#Filters] select 5, 'Filter', 'Filter2', 'filter_after_hours_offset=0,time_of_day_begin=00:00,worklistKey=1,worklistKey=2'
insert [#Filters] select 6, 'Filter', 'Filter3', 'filter_after_hours_offset=0,time_of_day_begin=00:00,worklistKey=2'
go
--select * from [#Filters]
I did not build this table, I am just trying to query from it.
I have a table called Filters. It contains two types, Filters and Worklists. Filters reference Worklists in the 'filtercriteria' column.
In the above example, Filter1 references WL1, Filter2 references WL1 and WL2, and Filter3 references WL2.
I need a query that will search the filters to ensure all of the Worklists are being referenced. For example, I want to be able to search the above table and for it to return WL3 because WL3 is not referenced in any of the filters.
There is other information in the filtercriteria column, so I'm not sure how to strip out everything except for the worklistKey info, and with that returned, just search for Worklists that aren't referenced in any Filter.
In SQL Server you can use XML functionality to parse a delimited field into multiple rows:
SELECT DISTINCT REPLACE(LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))),',','') AS filters
FROM
(SELECT filterid,CAST('<XMLRoot><RowData>' + REPLACE(filtercriteria,'worklistKey=','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM #Filters
WHERE filtertype = 'Filter'
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
WHERE ISNUMERIC(REPLACE(LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))),',','')) = 1
In this case we use 'worklistKey=' as the delimiter to parse on, and use an ISNUMERIC() check to filter out the non-numbers (rows that don't have a worklistKey).
This gets you the distinct list of Worklists referenced by Filters, you'll have to left-join from a list of all filters to finish this out. Might get messy if the reality is much different from your sample.

How to do an INSERT in SQL Server from a string containing a specific column

I'm trying to create a stored procedure that receives a string with the values of a specific column I want and then insert one row per each value, divided by "," .
For instance:
--The string I mentioned
#Objectid = '15, 21, 23, 53'.
--Then I wish to insert those values into a table like for instance
#Result( ID bigint, AppID bigint, ObjectID bigint)
So I wished to perform an insert on that table, and place the
values of each #Objectid onto a different row of #Result and on the
column ObjectID, while at the same time, filling other columns with
values I have stored in variables on the same stored procedure. Is there a way to do this? And if so, is there a way to do this without the usage of a cursor?
DECLARE #Objectid varchar(max);
set #Objectid = '15, 21, 23, 53';
set #Objectid = Replace(#Objectid, ',', '.');
SELECT ParseName(#Objectid, 4) As ID ,
ParseName(#Objectid, 3) As AppID ,
ParseName(#Objectid, 2) As ObjectID,
ParseName(#Objectid, 1) As ObjectID2

Not in In SQL statement?

I have set of ids in excel around 5000 and in the table I have ids around 30000. If I use 'In' condition in SQL statment I am getting around 4300 ids from what ever I have ids in Excel. But If I use 'Not In' with Excel id. I have getting around 25000+ records. I just to find out I am missing with Excel ids in the table.
How to write sql for this?
Example:
Excel Ids are
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
Table has IDs
1,
2,
3,
4,
6,
8,
9,
11,
12,
14,
15
Now I want get 5,7,10 values from Excel which missing the table?
Update:
What I am doing is
SELECT [GLID]
FROM [tbl_Detail]
where datasource = 'China' and ap_ID not in (5206896,
5206897,
5206898,
5206899,
5117083,
5143565,
5173361,
5179096,
5179097,
5179150)
Try this:
SELECT tableExcel.ID
FROM tableExcel
WHERE tableExcel.ID NOT IN(SELECT anotherTable.ID FROM anotherTable)
Here's an SQL Fiddle to try this: sqlfiddle.com/#!6/31af5/14
You're probably looking for EXCEPT:
SELECT Value
FROM #Excel
EXCEPT
SELECT Value
FROM #Table;
Edit:
Except will
treat NULL differently(NULL values are matching)
apply DISTINCT
unlike NOT IN
Here's your sample data:
declare #Excel Table(Value int);
INSERT INTO #Excel VALUES(1);
INSERT INTO #Excel VALUES(2);
INSERT INTO #Excel VALUES(3);
INSERT INTO #Excel VALUES(4);
INSERT INTO #Excel VALUES(5);
INSERT INTO #Excel VALUES(6);
INSERT INTO #Excel VALUES(7);
INSERT INTO #Excel VALUES(8);
INSERT INTO #Excel VALUES(9);
INSERT INTO #Excel VALUES(10);
declare #Table Table(Value int);
INSERT INTO #Table VALUES(1);
INSERT INTO #Table VALUES(2);
INSERT INTO #Table VALUES(3);
INSERT INTO #Table VALUES(4);
INSERT INTO #Table VALUES(6);
INSERT INTO #Table VALUES(8);
INSERT INTO #Table VALUES(9);
INSERT INTO #Table VALUES(11);
INSERT INTO #Table VALUES(12);
INSERT INTO #Table VALUES(14);
INSERT INTO #Table VALUES(15);
Import your excel file into SQL Server using the Import Data Wizard found in SQL Server Management Studio.
Then you can write the following query to find any IDs which are in the file but not in the table:
SELECT id
FROM imported_table
WHERE id NOT IN (SELECT id FROM db_table)
You should move excel data to a table in SQL Server, and then do the query in SQL Server.
select distinct id from Excel where id not in (select your ids from Sqltable)
(Obviously select your ids from Sqltable is a select which returns the Ids existing on SQL Server).
You may think that moving data to SQL Server is hard to do, but, on the contrary, it's very easy:
1) create a table
CREATE TABLE ExcelIds (Id int)
2) add a new column in excel with the following formula:
="insert into ExcelIds values(" & XX & ")"
where XX is the reference to the cell in the column with excel Ids.
3) copy the "inserts" from Excel into SSMS or whatever tool you're usin in SQL Server, and execute them.
Now you have 2 tables in SQL Server, so that querying it is absolutely easy.
When you're over, just drop the table
DROP TABLE ExcelIds
NOTE: I didn't create a key on SQL Server table because I suppose that the Ids can be repeated. Neither is justified to create a more complex SQL Query to avoid duplicates in ExcelIds for this ad hoc solution.