I have a problem with string.
I have a variable #Rights which looks like 'ASD,ZXC,QWE,IOP,JKL'
What I need to do is use this string in
SELECT * FROM dbo.Example
WHERE Rights IN (#Rights)
Problem is that I need to convert:
'ASD,ZXC,QWE,IOP,JKL'
to:
'ASD','ZXC','QWE','IOP','JKL'
How can I do this?
you can create a split function
CREATE FUNCTION [dbo].[Split]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
GO
and after you can convert the string in a temp table
DECLARE #Rights NVARCHAR(128)
SET #Rights = 'ASD,ZXC,QWE,IOP,JKL'
SELECT *
INTO #Temp
FROM dbo.Split(#Rights , ',')
and after you can use it in your query like this
SELECT * FROM dbo.Example
WHERE Rights IN (SELECT Data FROM #Temp)
You can try like this:
DECLARE #xml xml, #str varchar(100), #delimiter varchar(10)
SET #str = 'ASD,ZXC,QWE,IOP,JKL'
SET #delimiter = ','
SET #xml = cast(('<X>'+replace(#str, #delimiter, '</X><X>')+'</X>') as xml)
SELECT C.value('.', 'varchar(10)') as value FROM #xml.nodes('X') as X(C)
SQL DEMO
You can use Dynamic SQL:
LiveDemo
-- sample data
CREATE TABLE #Example(ID INT IDENTITY(1,1), Rights VARCHAR(100));
INSERT INTO #Example VALUES ('ASD'), ('ABC'), ('IOP');
DECLARE #Rights NVARCHAR(MAX) = 'ASD,ZXC,QWE,IOP,JKL';
DECLARE #sql NVARCHAR(MAX) =
N'SELECT *
FROM #Example
WHERE Rights IN (''<placeholder>'')';
SET #sql = REPLACE(#sql, '<placeholder>', REPLACE(#Rights, ',', ''','''));
-- SELECT #sql; -- for debug
EXEC dbo.sp_executesql
#sql;
But you should reconsider using Table Valued Parameter instead.
Related
Using PostgreSQL I can have multiple rows of json objects.
select (select ROW_TO_JSON(_) from (select c.name, c.age) as _) as jsonresult from employee as c
This gives me this result:
{"age":65,"name":"NAME"}
{"age":21,"name":"SURNAME"}
But in SqlServer when I use the FOR JSON AUTO clause it gives me an array of json objects instead of multiple rows.
select c.name, c.age from customer c FOR JSON AUTO
[{"age":65,"name":"NAME"},{"age":21,"name":"SURNAME"}]
How to get the same result format in SqlServer ?
By constructing separate JSON in each individual row:
SELECT (SELECT [age], [name] FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)
FROM customer
There is an alternative form that doesn't require you to know the table structure (but likely has worse performance because it may generate a large intermediate JSON):
SELECT [value] FROM OPENJSON(
(SELECT * FROM customer FOR JSON PATH)
)
no structure better performance
SELECT c.id, jdata.*
FROM customer c
cross apply
(SELECT * FROM customer jc where jc.id = c.id FOR JSON PATH , WITHOUT_ARRAY_WRAPPER) jdata (jdata)
Same as Barak Yellin but more lazy:
1-Create this proc
CREATE PROC PRC_SELECT_JSON(#TBL VARCHAR(100), #COLS VARCHAR(1000)='D.*') AS BEGIN
EXEC('
SELECT X.O FROM ' + #TBL + ' D
CROSS APPLY (
SELECT ' + #COLS + '
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
) X (O)
')
END
2-Can use either all columns or specific columns:
CREATE TABLE #TEST ( X INT, Y VARCHAR(10), Z DATE )
INSERT #TEST VALUES (123, 'TEST1', GETDATE())
INSERT #TEST VALUES (124, 'TEST2', GETDATE())
EXEC PRC_SELECT_JSON #TEST
EXEC PRC_SELECT_JSON #TEST, 'X, Y'
If you're using PHP add SET NOCOUNT ON; in the first row (why?).
I have a stored procedure in AZURE SQL database.In that there is a requirement to insert the records into the remote table from #temp table.
As xxxx_table is in the remote database used sp_execute_remote.
below is the scenario:
Create Procedure SP1 parameter1, Parameter2
As
select Distinct B.column1, B.Column2
into #A
from (Query1
Union
Query2) B
if (select count(1) from #A) > 0
Begin
Exec sp_execute_remote #data_source_name = N'Remotedatabase',
#stmt = N'INSERT INTO [dbo].[xxxx_table]
SELECT DISTINCT
'xxx' AS 'column1',
'xxx as 'Column2',
'xxx' AS 'Column3',
'xxx' AS 'Column4',
'xxx' AS Column4
FROM #A A INNER JOIN table1 on A.Column1 = Table1.Column2'
End
)
Getting the syntax error as below:
Incorrect syntax near 'xxx'.
Where am i going wrong? or let me know if there is another way to achieve this.
If you need to dynamically build a string in SQL single-quote the whole sentence, or use 'some text' + 'another text' to concat sentences. If you must add single quote use a double single quote ''
Example:
DECLARE #param1 int;
DECLARE #param1 VARCHAR(10);
SET #param1 = 10;
SET #param2 = 'CCDOS87'
#Stmt = 'SELECT Field1 FROM TableName WHERE Field1 = '
+ CAST(#param1 AS VARCHAR(100))
+ ' AND Field1 = '''
+ param2
+ ''''; <- This is a single '
#stmt = N'INSERT INTO [dbo].[Error_table]
SELECT DISTINCT
xxx AS column1,
xxx as Column2,
xxx AS Column3,
xxx AS Column4,
xxx AS Environment
FROM #A A INNER JOIN table1 on A.Column1 = Table1.Column2'
update
If your tables are in different databases but in the same server use:
INSERT INTO SERVER.SCHEMA.TABLE_NAME
SELECT Something
FROM SERVER.SCHEMA.TABLE_NAME
I need to do a query between two tables and find non matching fields
table 1 field locations has "my String"
table 2 field locations has "MY string"
they = by text but not by capitalization i need to return a false for this
Having the following data:
DECLARE #TableOne TABLE
(
[ID] TINYINT
,[Value] VARCHAR(12)
)
DECLARE #TableTwo TABLE
(
[ID] TINYINT
,[Value] VARCHAR(12)
)
INSERT INTO #TableOne ([ID], [Value])
VALUES (1,'my String')
INSERT INTO #TableTwo ([ID], [Value])
VALUES (1,'MY String')
You can use set Case Sentitive collation like this:
SELECT [TO].[Value]
,[TW].[Value]
FROM #TableOne [TO]
INNER JOIN #TableTwo [TW]
ON [TO].[ID] = [TW].[ID]
AND [TO].[Value] <> [TW].[Value]
COLLATE Latin1_General_CS_AS
or use HASH functions like this:
SELECT [TO].[Value]
,[TW].[Value]
FROM #TableOne [TO]
INNER JOIN #TableTwo [TW]
ON [TO].[ID] = [TW].[ID]
WHERE HASHBYTES('SHA1', [TO].[Value]) <> HASHBYTES('SHA1', [TW].[Value])
DECLARE #Table1 AS TABLE (FieldName VARCHAR(100))
DECLARE #Table2 AS TABLE (FieldName VARCHAR(100))
INSERT INTO #Table1 (FieldName) VALUES ('MY Location')
INSERT INTO #Table2 (FieldName) VALUES ('My Location')
With a default case insensitive collation order - Matches and returns results
SELECT * FROM #Table1 AS T1
INNER JOIN #Table2 AS T2
ON T1.FieldName = T2.FieldName
With a case sensitive collation order specified. Will not match
SELECT * FROM #Table1 AS T1
INNER JOIN #Table2 AS T2
ON T1.FieldName = T2.FieldName COLLATE Latin1_General_CS_AS_KS_WS
Microsoft article on collation
i want to search for a string in a CLOB:
some thing like id_name_2569
i get all my IDs i need like this:
select project_line_id as ID
from tbl1
where art_id in (
select art_id
from tbl2
where type = 3
);
and i search in this table:
A1 is a CLOB field
select * from tbl3 where dbms_lob.instr(A1, ID)>0;
obviously it isnt working i know, is here a way i could do this?
something like this should work:
select tbl3.*
from tbl1
inner join tbl2
on tbl2.art_id = tbl1.art_id
inner join tbl3
on tbl3.a1 like '%' || tbl1.project_line_id || '%'
where tbl2.type = 3;
You can use DBMS_LOB.instr directly as a join condition:
SELECT *
FROM (SELECT project_line_id AS ID
FROM tbl1
WHERE art_id IN (SELECT art_id FROM tbl2 WHERE TYPE = 3)) v
JOIN tbl3 ON dbms_lob.instr(tbl3.a1, v.ID) > 0
I'm trying to write a stored proc (SP) in Sybase.
The SP takes 5 varchar parameters.
Based on the parameters passed, I want to construct the column names to be selected from a particular table.
The below works:
DECLARE #TEST VARCHAR(50)
SELECT #TEST = "country"
--print #TEST
execute("SELECT DISTINCT id_country AS id_level, Country AS nm_level
FROM tempdb..tbl_books INNER JOIN
(tbl_ch2_bespoke_report INNER JOIN tbl_ch2_bespoke_rpt_mapping
ON tbl_ch2_bespoke_report.id_report = tbl_ch2_bespoke_rpt_mapping.id_report)
ON id_" + #TEST + "= tbl_ch2_bespoke_rpt_mapping.id_pnl_level
WHERE tbl_ch2_bespoke_report.id_report = 14")
but gives me multiple results:
1 1 row(s) affected.
id_level nm_level
1 4376 XYZ
2 4340 ABC
I would like to however only obtain the 2nd result.
Do I need to necessarily use dynamic SQL to achieve this?
Many thanks for your help.
--Chapax
If I'm understanding you correctly, you'd like to eliminate the "1 row(s) affected." line. If so, the "set nocount on/off" option should do the trick:
declare #something int
declare #query varchar(2000)
set nocount on
select #something=30
select #query = "SELECT * FROM a_table where id_row = " + convert(varchar(10),#something)
set nocount off
exec (#query)
or
declare #something int
declare #query varchar(2000)
set nocount on
select #something=30
set nocount off
SELECT * FROM a_table where id_row = #something
SET NOCOUNT {ON|OFF} to turn off row count messages.
Yes, you need to you dynamic SQL to change the structure or content of the result set (either the column list or the WHERE clause).