How do I print a triangle of stars using SQL - sql

Is it practically possible to create a triangle of stars like this as below in SQL.I know that this could be done easily in any other programming language like C,C++,Java but want to know whether it is really possible with just SQL or PL/SQL.I tried working on it with dual table in Oracle but couldn't get through it.
* *
* * * *
* * * or * * *
Can someone please shed somelight if anyone knows about it.

The simplest approach would be something like this. You can get more sophisticated particularly if you want to build the equilateral triangle rather than the right triangle.
SQL> ed
Wrote file afiedt.buf
1 select rpad( '* ', level*2, '* ' )
2 from dual
3* connect by level <= 3
SQL> /
RPAD('*',LEVEL*2,'*')
--------------------------------------------------------------------------------
*
* *
* * *

select rpad('* ', level * 2, '* ')
from dual connect by
level <= 10
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
select rpad(' ',r*2,' ')||rpad('* ',l*2,'* ') k
from ( select level l,row_number() over(order by null) r
from dual
connect by level<=10
order by l desc)
* * * * * * * * * *
* * * * * * * * *
* * * * * * * *
* * * * * * *
* * * * * *
* * * * *
* * * *
* * *
* *
*
select rpad(' ',l*2,' ')||rpad('* ',r*2,'* ') k
from ( select level l,row_number() over(order by null) r
from dual
connect by level<=10
order by l desc)
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
select rpad(' ',l,' ')||rpad('* ',r*2,'* ') k
from ( select level l,row_number() over(order by null) r
from dual
connect by level<=10
order by l desc)
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *

Not sure what you are looking for exactly. Perhaps this?
select '*' from dual
union all select '**' from dual
union all select '***' from dual
Example

Here is the script to Get a perfect triangle or Pyramid in sql (tested in Microsoft Sql 2008)
declare #x int,#y int
select #x=5,#y=0
while #x>0
begin
print space(#x)+replicate('*',#y)+replicate('*',#y+1)
set #y=#y+1
set #x=#x-1
end
*
***
*****
*******
*********
you can get many more scripts and help at this link... it was helpful to me
Link:- sqlquerynscript

Try this..
declare #x int,#y int,#diff int
select #x=0,#y=10,#diff=2--diferrence between consecutive rows
while #x<#y
begin
if #x=0 and #diff<>1
print space((#y-#x)*#diff-1)+replicate('*',1)
else if(#diff%2=0)
print space((#y-#x)*#diff)+replicate('* ',#x+(#x*(#diff-1)))
else
print space((#y-#x)*#diff)+replicate('* ',#x+(#x*(#diff-1)))
select #x=#x+1
end

If all you want is the simple triangle, then you can do this:
SELECT '*' FROM table
UNION
SELECT '**' FROM table
UNION
SELECT '***' FROM table

declare #count int,#num int,#num1 int, #space int, #str varchar(50)
set #count = 5 set #num = 1
while(#num<=#count)
begin
set #num1 = 0 set #space = #count-#num
while (#num1<#num)
begin
if #str is null
set #str = '* '
else
set #str = #str+'* ' set #num1 = #num1+1
end
print (space(#space)+#str)
set #num = #num+1 set #str = null
end

[Equilateral Traingle] We can make a pyramid with Oracle SQL as follows.
select rpad(' ',5 -level) || rpad( '* ', level*2, '* ' )
from dual
connect by level <= 5;
** Here 5 is the number of lines.
Let us reverse it,
select rpad(' ',level) || rpad( '* ', 2*(5-level+1), '* ' )
from dual
connect by level <= 5;

declare #row int = 5,
#index int = 0,
#string nvarchar(5) =''
while #row > 0
begin
set #index = #row
while #index > 0
begin
set #string = '*' + #string
set #index = #index - 1
end
print #string
set #string = ''
set #row = #row - 1
end
*****
****
***
**
*

DECLARE #lclMaxLevel INT=5
DECLARE #lclPrintCount INT =0
WHILE #lclMaxLevel > 0
BEGIN
PRINT Space(#lclMaxLevel)
+ Replicate('*', #lclPrintCount+1)
SET #lclMaxLevel=#lclMaxLevel - 1
SET #lclPrintCount=#lclPrintCount + 1
END

Related

Iterate each row and perform update accordingly

I have PostgreSQL SQL that should look for a backslash in a column called source_username and if it finds the backslash, it should replace the current value of the source_username column with the same value without the characters before the backslash.
For example:
before source_username: domain\username
after source_username: username
with os_user as (
select source_username from itpserver.managed_incidents mi;
),
osUserWithoutDomain as (
select (
case when (select * from os_user) ilike '%\\%' and (select position('-' in (select * from os_user))>= 1) and (select length((select * from os_user)) != (select position('-' in (select * from os_user))) + 1)
then (
select substring(
(select * from os_user),(select position('\' in (select * from os_user)) + 1),(select length((select * from os_user)) - 1)
))
else ((select * from os_user))
end
)
)
UPDATE itpserver.managed_incidents SET source_username = replace(source_username, (select * from os_user), (select * from osUserWithoutDomain)),
description = replace(description , (select * from os_user), (select * from osUserWithoutDomain)),
additional_info = replace(additional_info , (select * from os_user), (select * from osUserWithoutDomain)),
typical_behavior = replace(typical_behavior , (select * from os_user), (select * from osUserWithoutDomain)),
raw_description = replace(raw_description , (select * from os_user), (select * from osUserWithoutDomain));
This SQL works fine when I have only one row in the table.
If I have multiple rows, I need to specify the row that I want to work with by adding where id = <id>
I wish to iterate all the relevant rows (all the rows that source_username contains backslash) and on each row to perform the SQL above.
I tried to do this with LOOP:
create or replace function fetcher()
returns void as $$
declare
emp record;
begin
for emp in select *
from itpserver.managed_incidents
order by id
limit 10
loop
raise notice '%', emp.id;
<my sql> where id = emp.id
end loop;
end;
$$language plpgsql;
select fetcher();
However, I get an error because I don't think it likes the 'with' statement.
Any idea how can I do it?
It's far simpler than that. You need to use the SUBSTR and STRPOS functions. Take a look at the results of this query.
https://dbfiddle.uk/9-yPKn6E
with os_user (source_username) as (
select 'domain\username'
union select 'mydomain\joe'
union select 'janet'
)
select u.source_username
, strpos(u.source_username, '\')
, substr(u.source_username, strpos(u.source_username, '\') + 1)
from os_user u
source_username
strpos
substr
domain\username
7
username
janet
0
janet
mydomain\joe
9
joe
What you need is:
UPDATE itpserver.managed_incidents
SET source_username = substr(source_username, strpos(source_username, '\') + 1)
, description = replace(description , source_username, substr(source_username, strpos(source_username, '\') + 1))
, additional_info = replace(additional_info , source_username, substr(source_username, strpos(source_username, '\') + 1))
, typical_behavior = replace(typical_behavior , source_username, substr(source_username, strpos(source_username, '\') + 1))
, raw_description = replace(raw_description , source_username, substr(source_username, strpos(source_username, '\') + 1));
This is based on lengthy experience with SQL Server and some quick document searches for Postgresql. The UPDATE statement may not work as I expect.
SQL by design/default works on complete data sets. It thus eliminates LOOPS entirely from the language - they are not needed. (Well not quite there are recursive queries). Your task is accomplished in a single update statement with a simple regular expression. See documentation String Functions:
update managed_incidents
set source_username = regexp_replace(source_username,'.*\\(.*)','\1');
Demo here.
Main Take away: Drop procedural logic terminology (for, loop, if then, ...) from your SQL vocabulary. (you choose alternatives with case.)

Combining multiple rows into single one using CLOB

I'm having a trouble with saving multiple rows of a query into single one using CLOB.
I've tried this method suggested at ASK TOM https://asktom.oracle.com/pls/apex/f?p=100:11:::NO::P11_QUESTION_ID:9537158500346658848
but i think i'm lacking some knowledge to properly bind variables of my query.
Could you please help me? or maybe there is another option for this query to be compressed into single row using a CLOB
Here is the query in question
Select '<?xml version="1.0" encoding="UTF-8"?>'||chr(10)||
'<OtherServices ServiceMonth="'|| to_char(framework.dim_calendar_pkg.get_startdate(FRAMEWORK.CTL_Session_Parameters_PKG.Get_BillingPeriod()),'YYYYMM')||'" Source ="CLIENT" UniqueFileID ="ID0000036">' as XML
from dual
union all
select CAST(XML as varchar2(2000)) as XML from (
with CTE as
(SELECT R.BS_TEXT AS BillingDriver
, F.CI_NAME AS Signum
, 1 AS Quantity -- not F.Quantity, as even non-billable should have quantity 1
, CASE WHEN F.QUANTITY=0
THEN 'No'
ELSE 'Yes'
END AS Billable
FROM CLIENT.FACTS F
JOIN CLIENT.DIM_RESOURCEUNITS_VW R ON F.RU_ID = R.RU_ID
WHERE F.BILLINGPERIOD = FRAMEWORK.CTL_Session_Parameters_PKG.Get_BillingPeriod()
AND F.BILLINGPERIOD = F.SERVICEPERIOD
AND F.INPUT_SOURCE IN ('CLIENT_CVS_NONPDV','CLIENT_CVS_PDV','CLIENT_CVS_PV')
)
SELECT
XMLSERIALIZE(document
XMLElement("Service",
XMLForest (C.BillingDriver AS "BillingDriver",
C.Signum AS "Signum",
C.Quantity AS "Quantity",
C.Billable AS "Billable")
)
indent size=2) XML
FROM CTE C)
UNION ALL
Select '</OtherServices>' AS XML from dual;
SELECT '201904' AS ServiceMonth
, 'CLIENT' AS Source
, 'ID0000038' AS UniqueFileID
, 'ViCS_MWPII_user' AS BillingDriver
, VM.SIGNUM AS "Signum-ID"
, 1 AS Quantity
, 'Yes' AS Billable
FROM CLIENT.REF_CVS_VICS_MATRIX_VW VM
WHERE VM.ACCESS_TO_VICS_BASE = 1
AND (VM.ACCESS_TO_VICS_DESTKOP_EMEA = 1 OR VM.ACCESS_TO_VICS_DESTKOP_AMCS = 1 OR VM.ACCESS_TO_VICS_DESTKOP_APAC = 1)
AND EXISTS (SELECT 1 from CLIENT.FACTS F
WHERE F.BILLINGPERIOD = FRAMEWORK.CTL_Session_Parameters_PKG.Get_BillingPeriod()
AND F.BILLINGPERIOD = F.SERVICEPERIOD
AND F.INPUT_SOURCE IN ('CLIENT_MWP2_OPER','CLIENT_MWP2_COMP')
AND UPPER(F.CURRENT_USER) = UPPER(VM.SIGNUM))
UNION ALL
-- Signums with VICS_BASE and one of regional VICS_DESKTOPS, but without user in MWPII
SELECT '201904' AS ServiceMonth
, 'CLIENT' AS Source
, 'ID0000038' AS UniqueFileID
, 'ViCS_PV' AS BillingDriver
, VM.SIGNUM AS "Signum-ID"
, 1 AS Quantity
, 'Yes' AS Billable
FROM CLIENT.REF_CVS_VICS_MATRIX_VW VM
WHERE VM.ACCESS_TO_VICS_BASE = 1
AND (VM.ACCESS_TO_VICS_DESTKOP_EMEA = 1 OR VM.ACCESS_TO_VICS_DESTKOP_AMCS = 1 OR VM.ACCESS_TO_VICS_DESTKOP_APAC = 1)
AND NOT EXISTS (SELECT 1 from CLIENT.FACTS F
WHERE F.BILLINGPERIOD = FRAMEWORK.CTL_Session_Parameters_PKG.Get_BillingPeriod()
AND F.BILLINGPERIOD = F.SERVICEPERIOD
AND F.INPUT_SOURCE IN ('CLIENT_MWP2_OPER','CLIENT_MWP2_COMP')
AND UPPER(F.CURRENT_USER) = UPPER(VM.SIGNUM))
UNION ALL
-- Other signums with VICS_Base =1, but without regional VICS_Desktop
SELECT '201904' AS ServiceMonth
, 'CLIENT' AS Source
, 'ID0000038' AS UniqueFileID
, 'ViCS_Apps' AS BillingDriver
, VM.SIGNUM AS "Signum-ID"
, 1 AS Quantity
, 'Yes' AS Billable
FROM CLIENT.REF_CVS_VICS_MATRIX_VW VM
WHERE VM.ACCESS_TO_VICS_BASE = 1
AND (VM.ACCESS_TO_VICS_DESTKOP_EMEA IS NULL OR VM.ACCESS_TO_VICS_DESTKOP_EMEA != 1)
AND (VM.ACCESS_TO_VICS_DESTKOP_AMCS IS NULL OR VM.ACCESS_TO_VICS_DESTKOP_AMCS != 1)
AND (VM.ACCESS_TO_VICS_DESTKOP_APAC IS NULL OR VM.ACCESS_TO_VICS_DESTKOP_APAC != 1)
Thank you
Here is an example to convert multiple rows of data into a single CLOB value delimited by newline. In the cursor part you may want to replace with your query.
create table test(c clob);
declare
lv_clob CLOB;
cursor c
is select rpad('*',level*2,' *')||chr(10) rec from dual connect by level <= 15;
c_rec varchar2(100);--Holds each record from above cursor in each iteration
begin
dbms_lob.createtemporary(lv_clob, TRUE);
open c;
loop
fetch c into c_rec;
exit when c%notfound;
dbms_lob.append(lv_clob, c_rec);
end loop;
insert into test values(lv_clob);
commit;
dbms_lob.freetemporary(lv_clob);
end;
select * from test;
Output:
C
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * * * *
* * * * * * * * * * * * * * *

Convert Recursive CTE to Recursive Subquery

How would I convert the following CTE into a recursive subquery? It's an implementation of Newtons Method.
Reasons:
1) I have no permissions to create functions or stored procs in the DB
2) I must do everything in TSQL
3) Not using Oracle
TESTDATA Table
PMT t V
6918.26 6 410000
3636.51 14 460000
3077.98 22 630000
1645.14 18 340000
8591.67 13 850000
Desired Output
PMT t V Newton
6918.26 6 410000 0.066340421
3636.51 14 460000 0.042449138
3077.98 22 630000 0.024132674
1645.14 18 340000 0.004921588
8591.67 13 850000 0.075982984
_
DECLARE #PMT AS FLOAT
DECLARE #t AS FLOAT
DECLARE #V AS FLOAT
--These will be only for 1 example.
SET #PMT = 6918.26740930922
SET #t = 6
SET #V = 410000
;With Newton (n, i,Fi,dFi) AS (
--base
SELECT
1,
CAST(0.1 AS FLOAT)
,#PMT * (1 - POWER((1 + CAST(0.1 AS FLOAT) / 12), (-#t * 12))) - #V * CAST(0.1 AS FLOAT) / 12
,#PMT * #t * 12 * POWER((1 + CAST(0.1 AS FLOAT) / 12), (-#t * 12 - 1)) - #V
UNION ALL
--recursion
SELECT
n + 1
,i - Fi/dFi
,#PMT * (1 - POWER((1 + i / 12), (-#t * 12))) - #V * i / 12
,#PMT * #t * 12 * POWER((1 + i / 12), (-#t * 12 - 1)) - #V
FROM Newton WHERE n < 500)
--to get the desired value for params above
SELECT [x].i
FROM (
SELECT n, i, Fi, dFi
FROM Newton
WHERE n = 500
) [x]
OPTION (MAXRECURSION 500)
_
I want Newton to evaluate on Every record of TestData as a stand alone column.
Any thoughts?

Seeking SQL syntax with errors using HAVING with assigned variable

I am looking for the SQL syntax to use HAVING in the following statement:
DECLARE #ORIG_LAT AS FLOAT = 40.4882011413574;
DECLARE #ORIG_LONG AS FLOAT = -80.1939010620117;
DECLARE #DISTANCE AS INT;
SELECT LATITUDE_DEG, LONGITUDE_DEG,SQRT(
POWER(69.1 * (LATITUDE_DEG - #ORIG_LAT), 2) +
POWER(69.1 * (#ORIG_LONG - LONGITUDE_DEG) * COS(LATITUDE_DEG / 57.3), 2)) AS DISTANCE
FROM NAVAIDS
HAVING DISTANCE < 80 --error
ORDER BY DISTANCE ASC;
Error:
Msg 207, Level 16, State 1, Line 9
Invalid column name 'distance'.
It's ok with the ORDER BY but I don't understand why it doesn't like the HAVING. Any help with direction? It is SQL Server 2008 R2
As you have noticed, you can't use an aliased column directly. The easiest solution would be to wrap your statement in a subselect and apply your clause on that.
SELECT *
FROM (
SELECT LATITUDE_DEG
, LONGITUDE_DEG
, SQRT(
POWER(69.1 * (LATITUDE_DEG - #ORIG_LAT), 2) +
POWER(69.1 * (#ORIG_LONG - LONGITUDE_DEG) * COS(LATITUDE_DEG / 57.3), 2)) AS DISTANCE
FROM NAVAIDS
) q
WHERE DISTANCE < 80
ORDER BY
DISTANCE ASC;
select *
from (
SELECT LATITUDE_DEG, LONGITUDE_DEG, SQRT(
POWER(69.1 * (LATITUDE_DEG - #ORIG_LAT), 2)
POWER(69.1 * (#ORIG_LONG - LONGITUDE_DEG) * COS(LATITUDE_DEG / 57.3), 2)
) AS DISTANCE
FROM NAVAIDS
) a
WHERE DISTANCE < 80
ORDER BY DISTANCE

split comma separated values into distinct rows

I have a table which looks like this:
id fk_det userid
3 9 name1,name2
6 1 name3
9 2 name4,name5
12 3 name6,name7
I have already learned to regret having the values of the userid in comma separated values, so i want to split the rows up and end up with something that looks like
id fk_det userid
3 9 name1
x 9 name2
6 1 name3
9 2 name4
x 2 name5
12 3 name6
x 3 name7
i had been looking at something like this:
select fk_det, det, LEFT(userid, CHARINDEX(',',userid+',')-1),
STUFF(userid, 1, CHARINDEX(',',userid+','), '')
from global_permissions
but i'm not sure how to make it work when userid contains more than 2 items (which it might, some might have none, some might have multiple, just depends)
this is what I tend to use:
IF EXISTS (
SELECT 1
FROM dbo.sysobjects
WHERE id = object_id(N'[dbo].[ParseString]')
AND xtype in (N'FN', N'IF', N'TF'))
BEGIN
DROP FUNCTION [dbo].[ParseString]
END
GO
CREATE FUNCTION dbo.ParseString (#String VARCHAR(8000), #Delimiter VARCHAR(10))
RETURNS TABLE
AS
/*******************************************************************************************************
* dbo.ParseString
*
* Creator: magicmike
* Date: 9/12/2006
*
*
* Outline: A set-based string tokenizer
* Takes a string that is delimited by another string (of one or more characters),
* parses it out into tokens and returns the tokens in table format. Leading
* and trailing spaces in each token are removed, and empty tokens are thrown
* away.
*
*
* Usage examples/test cases:
Single-byte delimiter:
select * from dbo.ParseString2('|HDI|TR|YUM|||', '|')
select * from dbo.ParseString2('HDI| || TR |YUM', '|')
select * from dbo.ParseString2(' HDI| || S P A C E S |YUM | ', '|')
select * from dbo.ParseString2('HDI|||TR|YUM', '|')
select * from dbo.ParseString2('', '|')
select * from dbo.ParseString2('YUM', '|')
select * from dbo.ParseString2('||||', '|')
select * from dbo.ParseString2('HDI TR YUM', ' ')
select * from dbo.ParseString2(' HDI| || S P A C E S |YUM | ', ' ') order by Ident
select * from dbo.ParseString2(' HDI| || S P A C E S |YUM | ', ' ') order by StringValue
Multi-byte delimiter:
select * from dbo.ParseString2('HDI and TR', 'and')
select * from dbo.ParseString2('Pebbles and Bamm Bamm', 'and')
select * from dbo.ParseString2('Pebbles and sandbars', 'and')
select * from dbo.ParseString2('Pebbles and sandbars', ' and ')
select * from dbo.ParseString2('Pebbles and sand', 'and')
select * from dbo.ParseString2('Pebbles and sand', ' and ')
*
*
* Notes:
1. A delimiter is optional. If a blank delimiter is given, each byte is returned in it's own row (including spaces).
select * from dbo.ParseString3('|HDI|TR|YUM|||', '')
2. In order to maintain compatibility with SQL 2000, ident is not sequential but can still be used in an order clause
If you are running on SQL2005 or later
SELECT Ident, StringValue FROM
with
SELECT Ident = ROW_NUMBER() OVER (ORDER BY ident), StringValue FROM
*
*
* Modifications
*
*
********************************************************************************************************/
RETURN (
SELECT Ident, StringValue FROM
(
SELECT Num as Ident,
CASE
WHEN DATALENGTH(#delimiter) = 0 or #delimiter IS NULL
THEN LTRIM(SUBSTRING(#string, num, 1)) --replace this line with '' if you prefer it to return nothing when no delimiter is supplied. Remove LTRIM if you want to return spaces when no delimiter is supplied
ELSE
LTRIM(RTRIM(SUBSTRING(#String,
CASE
WHEN (Num = 1 AND SUBSTRING(#String,num ,DATALENGTH(#delimiter)) <> #delimiter) THEN 1
ELSE Num + DATALENGTH(#delimiter)
END,
CASE CHARINDEX(#Delimiter, #String, Num + DATALENGTH(#delimiter))
WHEN 0 THEN LEN(#String) - Num + DATALENGTH(#delimiter)
ELSE CHARINDEX(#Delimiter, #String, Num + DATALENGTH(#delimiter)) - Num -
CASE
WHEN Num > 1 OR (Num = 1 AND SUBSTRING(#String,num ,DATALENGTH(#delimiter)) = #delimiter)
THEN DATALENGTH(#delimiter)
ELSE 0
END
END
)))
End AS StringValue
FROM dbo.Numbers
WHERE Num <= LEN(#String)
AND (
SUBSTRING(#String, Num, DATALENGTH(ISNULL(#delimiter,''))) = #Delimiter
OR Num = 1
OR DATALENGTH(ISNULL(#delimiter,'')) = 0
)
) R WHERE StringValue <> ''
)
You would use it like this:
SELECT id, pk_det, V.StringValue as userid
FROM myTable T
OUTER APPLY dbo.ParseString(T.userId) V
The UDF requires a 'tally' or Number table which assumes the following schema:
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Numbers')
BEGIN
CREATE TABLE dbo.Numbers
(
Num INT NOT NULL
CONSTRAINT [PKC__Numbers__Num] PRIMARY KEY CLUSTERED (Num) on [PRIMARY]
)
;WITH Nbrs_3( n ) AS ( SELECT 1 UNION SELECT 0 ),
Nbrs_2( n ) AS ( SELECT 1 FROM Nbrs_3 n1 CROSS JOIN Nbrs_3 n2 ),
Nbrs_1( n ) AS ( SELECT 1 FROM Nbrs_2 n1 CROSS JOIN Nbrs_2 n2 ),
Nbrs_0( n ) AS ( SELECT 1 FROM Nbrs_1 n1 CROSS JOIN Nbrs_1 n2 ),
Nbrs ( n ) AS ( SELECT 1 FROM Nbrs_0 n1 CROSS JOIN Nbrs_0 n2 )
INSERT INTO dbo.Numbers(Num)
SELECT n
FROM ( SELECT ROW_NUMBER() OVER (ORDER BY n)
FROM Nbrs ) D ( n )
WHERE n <= 50000 ;
END
Numbers tables are an invaluable addition to your toolset. To quote Adam Machanic:
Numbers tables are truly invaluable. I use them all of the time for
string manipulation, simulating window functions, populating test
tables with lots of data, eliminating cursor logic, and many other
tasks that would be incredibly difficult without them.
Is using a table of numbers a hack, as I've seen some people claim?
No. Show me another way to efficiently do all of the things a numbers
table can. Does it waste space? No. The script below will use up
around 900 KB of disk space in each database. That's absolutely
nothing. You'll end up getting millions, maybe billions of times the
disk space investment back in terms of ease of development and time
saved.
http://dataeducation.com/you-require-a-numbers-table/
Try this :)
DECLARE #Name TABLE
(
id INT NULL ,
fk_det INT NULL ,
userid NVARCHAR(100) NULL
)
INSERT INTO #Name
( id, fk_det, userid)
VALUES (3,9,'name1,name2' )
INSERT INTO #Name
( id, fk_det, userid)
VALUES (6,1,'name3' )
INSERT INTO #Name
( id, fk_det, userid)
VALUES (9,2,'name4,name5' )
INSERT INTO #Name
( id, fk_det, userid)
VALUES (12,3,'name6,name7' )
SELECT *
FROM #Name
SELECT id,A.fk_det,
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT id,fk_det,
CAST ('<M>' + REPLACE(userid, ',', '</M><M>') + '</M>' AS XML) AS String
FROM #Name) AS A CROSS APPLY String.nodes ('/M') AS Split(a);
As an alternative to the standard sproc call you see everywhere:
with temp as(
select id,fk_det,cast('<comma>'+replace(userid,',','</comma><comma>')+'</comma>' as XMLcomma
from global_permissions
)
select id,fk_det,a.value('comma[1]','varchar(512)')
cross apply temp.XMLcomma.nodes('/comma') t(a)