Sunteți pe pagina 1din 22

04/04/12

Concatenating Row Values in Transact-SQL

Home

SQL

.NET

SysAdmin

Opinion

Blogs

Forums

Books

Signin|Join|Help

SQLHome>TSQLProgramming>ConcatenatingRowValuesinTransactSQL

ConcatenatingRowValuesinTransact SQL
31July2008 byAnithSen

Avrating: Totalvotes:346 Totalcomments:58 sendtoafriend printerfriendlyversion

SQLHome LearnSQLServer (80articles) SQLTraining (10articles) DatabaseAdministration (118articles) TSQLProgramming (131articles)

ItisaninterestingprobleminTransactSQL,forwhichthereareanumberofsolutionsand considerabledebate.Howdoyougoaboutproducingasummaryresultinwhichadistinguishing columnfromeachrowineachparticularcategoryislistedina'aggregate'column?Asimple,and intuitivewayofdisplayingdataissurprisinglydifficulttoachieve.AnithSengivesasummaryof differentways,andofferswordsofcautionovertheoneyouchoose.

Performance (34articles) BackupandRecovery (26articles) SQLTools (72articles) SSIS (21articles) ReportingServices (20articles)

Contents
Introduction. Acoreissue. Considerations Concatenatingvalueswhenthenumberofitemsissmallandknownbeforehand Concatenatingvalueswhenthenumberofitemsisnotknown. RecursiveCTEmethods TheblackboxXMLmethods UsingCommonLanguageRuntime. ScalarUDFwithrecursion. TablevaluedUDFwithaWHILEloop. DynamicSQL TheCursorapproach. Unreliableapproaches ScalarUDFwithtSQLupdateextension. ScalarUDFwithvariableconcatenationinSELECT Conclusion. References Acknowledgements

SQL .NET SysAdmin Opinion Books Blogs

Ifyouupdateyourfeed, pleaseremembertotell yourRSSreaderthe newURL Clickhereforadvanced RSSoptions

Introduction
Many a time, SQL programmers are faced with a requirement to generate reportlike resultsets directly from a Transact SQL query. In most cases, the requirement arises from the fact that there neither sufficient tools nor in houseexpertisetodeveloptoolsthatcanextractthedataasaresultset,andthenmassagethedatainthedesired displayformat.Quiteoftenfolksareconfusedaboutthepotentialofbreakingrelationalfundamentalssuchasthe FirstNormalFormorthescalarnatureoftypedvalues.(Talkingabout1NFviolationsinalanguagelikeSQLwhich lackssufficientdomainsupport,allowsNULLsandsupportsduplicatesissomewhatironictobeginwith,butthatisa topicwhichrequiresdetailedexplanations.) By'Concatenatingrowvalues'wemeanthis: Youhaveatable,vieworresultthatlookslikethis... ...andyouwishtohavearesultsetliketheonebelow: InthisexampleweareaccessingthesampleNorthWinddatabase andusingthefollowingSQL

GeneratingDataforDatabaseTests Itismoreandmoreessentialfor developerstoworkondevelopment databasesthathaverealisticdatainboth type... Readmore... RECENTBLOGPOSTS: ASliceofRaspberryPi DatabaseMigrationScripts:Gettingfromplace... Normalisationand'Animanotitiacopia'(Soul... Viewtheblog

SLCaeoydrdcNm EETCtgrI,Poutae FOotwn.Pout RMNrhid.rdcs

ImplementingForeachLoopingLogicinSSIS WithSSIS,itispossibletoimplementloopinglogicinto SSIS'scontrolflowinordertodefinea...Readmore... GeneratingDataforDatabaseTests Itismoreandmoreessentialfordeveloperstowork ondevelopmentdatabasesthathaverealistic data...Readmore... SQLSourceControl:TheDevelopmentStory Often,thereisahugedifferencebetweensoftware beingeasytouse,andeasytodevelop.When your...Readmore... HowtoImportDatafromHTMLpages Itturnsoutthatthereareplentyofwaystogetdata intoSQLServerfromwebsites,whetherthe data...Readmore... SQLScriptsManager:AnAppreciation SQLScriptsManagerisSimpleTalk'spresenttoits

Theobjectiveistoreturnaresultsetwithtwocolumns,onewiththe CategoryIdentifier,andtheotherwithaconcatenatedlistofallthe Product Names separated by a delimiting character: such as a comma.

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

1/22

04/04/12

Concatenating Row Values in Transact-SQL


readers.WilliamBrewerwasanenthusiastic...Read more...

BeginningSQLServer2005ReportingServicesPart 1 SteveJoubertbeginsanindepthtourofSQLServer 2005ReportingServiceswithastepbystep guide...Readmore... TenCommonDatabaseDesignMistakes Ifdatabasedesignisdoneright,thenthe development,deploymentandsubsequentperformance in...Readmore... ReadingandWritingFilesinSQLServerusingT SQL SQLServerprovidesseveral"standard"techniques bywhichtoreadandwritetofilesbut,just...Read more... BeginningSQLServer2005ReportingServicesPart 2 ContinuinghisindepthtourofSQLServer2005 ReportingServices,SteveJoubertdemonstratesthe most...Readmore... CreatingCSVFilesUsingBCPandStored Procedures NigelRivettdemonstratessomecoretechniquesfor extractingSQLServerdataintoCSVfiles, focussing...Readmore...

Over400,000Microsoftprofessionals subscribetotheSimpleTalktechnical journal.Jointoday,it'sfast,simple,free andsecure.

Concatenatingcolumnvaluesorexpressionsfrommultiplerowsareusuallybestdoneinaclientsideapplication language,sincethestringmanipulationcapabilitiesofTransactSQLandSQLbasedDBMSsaresomewhatlimited. However,youcandotheseusingdifferentapproachesinTransactSQL,butitisbesttoavoidsuchmethodsinlong termsolutions

Acoreissue
EventhoughSQL,ingeneral,deviatesconsiderablyfromtherelationalmodel,itsrelianceoncertaincoreaspects ofrelationalfoundationsmakesSQLfunctionalandpowerful.OnesuchcoreaspectisthesetbasednatureofSQL expressions(well,multisetstobeexact,butforthegivencontextletusignoretheissueofduplication).Theprimary ideaisthattablesareunorderedandthereforetheresultsetsofanyquerythatdoesnothaveanexplicitORDERBY clauseisunorderedaswell.Inotherwords,therowsinaresultsetofaquerydonothaveaprescribedposition, unlessitisexplicitlyspecifiedinthequeryexpression. Ontheotherhand,aconcatenatedlistisanorderedstructure.Eachelementinthelisthasaspecificposition.In fact,concatenationitselfisanorderutilizingoperationinthesensethatvaluescanbeprefixedorpostfixedtoan existing list. So approaches that are loosely called concatenating row values, aggregate concatenation etc. would have to make sure that some kind of an order, either explicit or implicit, should be specified prior to concatenatingtherowvalues.Ifsuchanorderingcriteriaisnotprovided,theconcatenatedstringwouldbearbitrary innature.

Considerations
Generally, requests for row value concatenations often comes in two basic flavors, when the number of rows is knownandsmall(typicallylessthan10)andwhenthenumberofrowsisunknownandpotentiallylarge.Itmaybe bettertolookateachofthemseparately. Insomecases,alltheprogrammerwantsisjustthelistofvaluesfromasetofrows.Thereisnogroupingorlogical partitioning of values such as the list of email addresses separated by a semicolon or some such. In such situations, the approaches can be the same except that the join conditions may vary. Minor variations of the exampleslistonthispageillustratesuchsolutionsaswell. For the purpose of this article the Products table from Northwind database is used to illustrate column value concatenationswithagroupingcolumn.NorthwindisasampledatabaseinSQLServer2000defaultinstallations. YoucandownloadacopyfromfromtheMicrosoftDownloads

Concatenatingvalueswhenthenumberofitemsissmallandknownbeforehand
Whenthenumberofrowsissmallandalmostknownbeforehand,itiseasiertogeneratethecode.Onecommon approachwherethereisasmallsetoffiniterowsisthepivotingmethod.Hereisanexamplewhereonlythefirst fouralphabeticallysortedproductnamespercategoryidisretrieved:

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

2/22

04/04/12

Concatenating Row Values in Transact-SQL


EETCtgrI, SLCaeoyd A(CSeHN1TErdcNmLE'N,'+ MXAEsqWEHNPoutaeES'ED)+' A(CSeHN2TErdcNmLE'N,'+ MXAEsqWEHNPoutaeES'ED)+' A(CSeHN3TErdcNmLE'N,'+ MXAEsqWEHNPoutaeES'ED)+' A(CSeHN4TErdcNmLE'N MXAEsqWEHNPoutaeES'ED) FOEETp.aeoyd1Poutae RM(SLC1CtgrI,p.rdcNm, (SLCON() EETCUT* FOotwn.b.rdcsp RMNrhiddoPout2 WEEp.aeoyd=p.aeoyd HR2CtgrI1CtgrI ADp.rdcNm=p.rdcNm N2Poutae<1Poutae) RMNrhiddoPout1)D(CtgrI,Poutaee FOotwn.b.rdcspaeoydrdcNm,sq) RUYCtgrI GOPBaeoyd

Theideahereistocreateaexpressioninsidethecorrelatedsubquerythatproducesarank(seq)basedonthe product names and then use it in the outer query. Using common table expressions and the ROW_NUMBER() function,youcanrewritethisas:
WTTaeoydrdcNm,sq) IHCE(CtgrI,Poutaee S(SLC1CtgrI,p.rdcNm, AEETp.aeoyd1Poutae RWNME(VR(PRIINBaeoydODRBrdcNm O_UBR)OEATTOYCtgrIREYPoutae) RMNrhiddoPout1) FOotwn.b.rdcsp SLCaeoyd EETCtgrI, A(CSeHN1TErdcNmLE'N,'+ MXAEsqWEHNPoutaeES'ED)+' A(CSeHN2TErdcNmLE'N,'+ MXAEsqWEHNPoutaeES'ED)+' A(CSeHN3TErdcNmLE'N,'+ MXAEsqWEHNPoutaeES'ED)+' A(CSeHN4TErdcNmLE'N MXAEsqWEHNPoutaeES'ED) RMCE FOT RUYCtgrI GOPBaeoyd

NotethatROW_NUMBER()isanewlyintroducedfeatureinSQL2005.Ifyouareusinganypreviousversion,you willhavetousethesubqueryapproach(Youcanalsouseaselfjoin,towriteitabitdifferently).Usingtherecently introducedPIVOToperator,youcanwritethisasfollows:


SLCaeoyd EETCtgrI, 1,'+""+'3,'+""Ardc_it ""+'2,'+""+'4SPoutLs FOEETCtgrI,Poutae RM(SLCaeoydrdcNm, RWNME(VR(ATTOYCtgrI O_UBR)OEPRIINBaeoyd REYPoutae ODRBrdcNm) RMNrhiddoPoutaeoydrdcNm,sq) FOotwn.b.rdcs)P(CtgrI,Poutaee IOA(Poutae)FRsqI1,""3,""))A_ PVT(MXrdcNmOeN(""2,""4SP

Notonlydoesthesyntaxappearabitconfusing,butalsoitdoesnotseemtoofferanymorefunctionalitythanthe previousCASEapproach.However,inraresituations,itcouldcomeinhandy.

Concatenatingvalueswhenthenumberofitemsisnotknown
Whenyoudonotknowthenumberofitemsthataretobeconcatenatedbeforehand,thecodecanbecomerather moredemanding.ThenewfeaturesinSQL2005makesomeoftheapproacheseasier.Forinstance,therecursive commontableexpressions(CTEs)andtheFORXMLPATH('')syntaxmakestheserverdothehardworkbehindthe concatenation,leavingtheprogrammertodealwiththepresentationissues.Theexamplesbelowmakethispoint obvious.

RecursiveCTEmethods
The idea behind this method is from a newsgroup posting by Vadim Tropashko. It is similar to the ideas behind generatingamaterializedpathforhierarchies.
WTTaeoydrdc_itrdc_aeegh) IHCE(CtgrI,poutls,poutnm,lnt AEETCtgrI,CS('SVRHR80))AT'A S(SLCaeoydAT'AACA(00,CS('S VRHR80)) ACA(00,0 RMNrhid.rdcs FOotwn.Pout GOPBaeoyd RUYCtgrI UINAL NOL EETpCtgrI,CS(poutls SLC.aeoydATrdc_it+ CSHNlntHN'LE'NrdcNmS AEWEegh=0TE'ES,'ED+PoutaeA VRHR80)) ACA(00, CS(PoutaeAACA(00)egh+1 ATrdcNmSVRHR80),lnt RMCEc FOT INRJIotwn.Pout NEONNrhid.rdcsp NcCtgrI.aeoyd O.aeoyd=pCtgrI WEEpPoutae>cpoutnm HR.rdcNm.rdc_ae) SLCaeoydrdc_it EETCtgrI,poutls FOEETCtgrI,poutls, RM(SLCaeoydrdc_it RN(VR(PRIINBaeoydODRBeghDS AK)OEATTOYCtgrIREYlntEC) RMCE)D(CtgrI,poutls,rn FOTaeoydrdc_itak) HRak=1 WEErn

TheCASEintherecursivepartoftheCTEisusedtoeliminatetheinitialcomma,butyoucanuseRIGHTorthe SUBSTRINGfunctionsinstead.Thismaynotbethebestperformingoption,butcertainadditionaltuningcouldbe donetomakethemsuitableformediumsizeddatasets. Another approach using recursive common table expressions was sent in by Anub Philip, an Engineer from

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

3/22

04/04/12

Concatenating Row Values in Transact-SQL

SathyamComputersthatusesseparatecommontableexpressionsfortheanchorandrecursiveparts.
WTakd(CtgrI,rkrdcNm IHRneaeoydn,Poutae) S(SLCaeoyd AEETCtgrI, O_UBR)OE(PRIINBaeoydODRB RWNME(VRATTOYCtgrIREY CtgrI, aeoyd) ATrdcNmSVRHR80)) CS(PoutaeAACA(00 FOotwn.Pout) RMNrhid.rdcs, nhrakd(CtgrI,rkrdcNm AcoRneaeoydn,Poutae) S(SLCaeoydn,Poutae AEETCtgrI,rkrdcNm FOakd RMRne HRn, WEErk=1) Rcrakd(CtgrI,rkrdcNm euRneaeoydn,Poutae) S(SLCaeoydn,Poutae AEETCtgrI,rkrdcNm FOnhrakd RMAcoRne NOL UINAL SLCakdCtgrI,Rne.n, EETRne.aeoydakdrk euRne.rdcNm,'+Rne.rdcNm RcrakdPoutae+'akdPoutae FOakd RMRne NEONRcrakd INRJIeuRne OakdCtgrIeuRne.aeoyd NRne.aeoyd=RcrakdCtgrI Nakdrk=Rcrakdrk+1) ADRne.neuRne.n SLCaeoydA(Poutae) EETCtgrI,MXrdcNm FOeuRne RMRcrakd GOPBaeoyd RUYCtgrI

On first glance, this query may seem a bit expensive in comparison, but the reader is encouraged to check the executionplansandmakeanyadditionaltweaksasneeded.

TheblackboxXMLmethods
HereisatechniqueforstringconcatenationthatusestheFORXMLclausewithPATHmode.Itwasinitiallyposted byEugeneKogan,andlaterbecamecommoninpublicnewsgroups.
SLC1CtgrI, EETp.aeoyd EETPoutae+'' (SLCrdcNm, RMNrhiddoPout2 FOotwn.b.rdcsp WEEp.aeoyd=p.aeoyd HR2CtgrI1CtgrI ODRBrdcNm REYPoutae FRXLPT('SPout OMAH'))Ardcs FOotwn.b.rdcsp RMNrhiddoPout1 GOPBaeoyd RUYCtgrI

Thereisasimilarapproachthatwasoriginallyfoundinthebetanewsgroups,usingtheCROSSAPPLYoperator.
SLCITNTCtgrI,Poutae EETDSICaeoydrdcNms FOotwn.b.rdcsp RMNrhiddoPout1 RSPLEETPoutae+'' COSAPY(SLCrdcNm, RMNrhiddoPout2 FOotwn.b.rdcsp HR2CtgrI1CtgrI WEEp.aeoyd=p.aeoyd REYPoutae ODRBrdcNm OMAH'))rdcNms) FRXLPT('D(Poutae

Youmaynoticeacommaattheendoftheconcatenatedstring,whichyoucanremoveusingaSTUFF,SUBSTRING or LEFT function. While the above methods are deemed reliable by many at the time of writing, there is no guarantee that it will stay that way, given that the internal workings and evaluation rules of FOR XML PATH() expressionincorrelatedsubqueriesarenotwelldocumented. TheproblemwiththisapproachisthatthecontentsoftheProductNamecolumnisinterpretedaXMLratherthan text,whichwillleadtocertaincharactersbeing'entitized',orinsomecases,leadingtotheSQLcausinganerror. (seenotebelow,andsolutionbyAdamMachanicincommentsbelow)andtoavoidthis,itisbettertouseaslightly revisedsyntaxlikethis..
SLC1CtgrI, EETp.aeoyd tf((EET''Poutae sufSLC,+rdcNm RMNrhiddoPout2 FOotwn.b.rdcsp HR2CtgrI1CtgrI WEEp.aeoyd=p.aeoyd REYPoutae ODRBrdcNm OMAH')YE.au(.,'aca(a)) FRXLPT(',TP)vle''vrhrmx' ,,,' 11') SPout Ardcs FOotwn.b.rdcsp RMNrhiddoPout1 GOPBaeoyd RUYCtgrI

...andthis...
SLCITNTCtgrI,Poutae EETDSICaeoydrdcNms FOotwn.b.rdcsp RMNrhiddoPout1 RSPLEET COSAPY(SLC tf((EET''Poutae sufSLC,+rdcNm

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

4/22

04/04/12

Concatenating Row Values in Transact-SQL


RMNrhiddoPout2 FOotwn.b.rdcsp HR2CtgrI1CtgrI WEEp.aeoyd=p.aeoyd REYPoutae ODRBrdcNm OMAH')YE.au(.,'aca(a)) FRXLPT(',TP)vle''vrhrmx' ,,,' 11') )rdcNms) D(Poutae

UsingCommonLanguageRuntime
ThoughthisarticleisaboutapproachesusingTransactSQL,thissectionisincludedduetothepopularityofCLR aggregatesinSQL2005.ItnotonlyempowerstheCLRprogrammerwithnewoptionsfordatabasedevelopment, butalso,insomecases,theyworkatleastaswellasnativeTransactSQLapproaches. If you are familiar with .NET languages, SQL 2005 offers a convenient way to create user defined aggregate functions using C#, VB.NET or similar languages that are supported by the Common Language Runtime (CLR). HereisanexampleofastringconcatenateaggregatefunctionwrittenusingC#.
uigSse snytm uigSse.olcin.eei snytmCletosGnrc uigSse.aaSlye snytmDt.qTps uigSse.O snytmI uigMcootSlevrSre snirsf.qSre.evr [eilzbe Sraial] [qUeDfndgrgt(omtUeDfndMxyeie80) SlsreieAgeaeFra.sreie,aBtSz=00] pbitutsroct:Iiayeilz{ ulcsrctcnaBnrSraie piaeLsaus rvtitvle pbiodIi({ ulcvint) ti.aus=nwLs( hsvleeit) } pbiodAcmlt(qSrnau) ulcvicuuaeSltigvle{ ti.ausAdvleVle hsvle.d(au.au) } pbiodMresroctvle{ ulcvieg(tcnaau) ti.ausAdag(au.ausTAry) hsvle.dRnevlevle.ora() } pbiqSrnemnt({ ulcSltigTriae) rtreqSrn(tigJi(,"hsvle.ora() eunnwSltigsrn.on",ti.ausTAry)) } pbiodRa(iayedrr{ ulcviedBnrRae) itieCut=rRaIt2) ntmon.edn3( ti.aus=nwLs(tmon) hsvleeitieCut fr(ni<tmoni+{ oiti=0=ieCut1+) ti.ausAdrRaSrn() hsvle.d(.edtig) } } pbiodWieBnrWie) ulcvirt(iayrtrw{ wWieti.ausCut .rt(hsvle.on) frah(tigsihsvle) oecsrnnti.aus{ wWies .rt() } } }

Onceyoubuildanddeploythisassemblyontheserver,youshouldbeabletoexecuteyourconcatenationqueryas:
SLCaeoyd EETCtgrI, b.tcna(rdcNm) dosroctPoutae FOrdcs RMPout RUYCtgrI GOPBaeoyd

IfyouareatotalnewbieonCLRlanguages,andwouldliketolearnmoreaboutdevelopingdatabasesolutions usingCLRlanguages,considerstartingatIntroductiontoCommonLanguageRuntime(CLR)Integration

ScalarUDFwithrecursion
RecursivefunctionsintSQLhaveadrawbackthatthemaximumnestinglevelis32.Sothisapproachisapplicable onlyforsmallerdatasets,especiallywhenthenumberofitemswithinagroup,thatneedstobeconcatenated,isless than32.
CETUCINufrcrie(@iN,@N RAEFNTOd_eusvcdITiIT) RTRSVRHR80)AEI EUNACA(00SBGN DCAE@ACA(00,@ACA(00 ELRrVRHR80)lVRHR80) SLCi=@,r=Poutae+' EET@i1@rdcNm,'

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

5/22

04/04/12

Concatenating Row Values in Transact-SQL


FOotwn.Pout1 RMNrhid.rdcsp HRaeoyd=@i WEECtgrIcd Ni=(SLCON()FOotwn.Pout2 AD@EETCUT*RMNrhid.rdcsp HR2CtgrI1CtgrI WEEp.aeoyd=p.aeoyd N2Poutae<1Poutae) ADp.rdcNm=p.rdcNm Ii>0BGN F@EI EEl=doufrcrie@i,@ XC@b.d_eusvcdi ST@@r Er=l+@ ED N RTRr EUN@ ED N

Thisfunctioncanbeinvokedasfollows:
SLCaeoyd EETCtgrI, b.d_eusv(CtgrI,CUTPoutae doufrcrieaeoydON(rdcNm)) FOotwn.Pout RMNrhid.rdcs RUYCtgrI GOPBaeoyd

TablevaluedUDFwithaWHILEloop
ThisapproachisbasedontheideabyLindaWierzbeckiwhereatablevariablewiththreecolumnsisusedwithina tablevaluedUDF.Thefirstcolumnrepresentsthegroup,secondrepresentsthecurrentlyprocessingvaluewithina groupandthethirdrepresentstheconcatenatedlistofvalues.
CETUCINuftlCna(EUNtTBE RAEFNTOd_b_oct)RTRS@AL( CtgrIN, aeoydIT PoutVRHR4) rdcACA(0, lsACA(00 itVRHR80)) BGN EI NET@CtgrI,Poutit ISRt(aeoydrdc,ls) EETCtgrI,MNPoutae,I(rdcNm) SLCaeoydI(rdcNm)MNPoutae RMPout FOrdcs GOPBaeoyd RUYCtgrI WIE(SLCON(rdc)FOt)>0BGN HLEETCUTPoutRM@EI UDT PAEt Eit=lsOLSE STlsit+CAEC( EET'I(Poutae) (SLC,'+MNrdcNm RMNrhid.rdcs FOotwn.Pout WEEPout.aeoyd=tCtgrI HRrdcsCtgrI.aeoyd ADPout.rdcNm.rdc)', NrdcsPoutae>tPout,') rdcEETMNPoutae Pout=(SLCI(rdcNm) RMNrhid.rdcs FOotwn.Pout WEEPout.aeoyd=tCtgrI HRrdcsCtgrI.aeoyd ADPout.rdcNm.rdc NrdcsPoutae>tPout) FOttED RM@N RTR EUN ED N

Theusageoftheabovefunctioncanbelike:
SLCaeoyditArdcs EETCtgrI,lsSPout FOd_b_oct) RMuftlCna(

DynamicSQL
Thisapproachisavariationofthekludgeoftenknownusingthenicknameofdynamiccrosstabulation.Thereis enoughliteratureouttherewhichdemonstratesthedrawbacksandimplicationsofusingDynamicSQL.Apopular one,atleastfromTransactSQLprogrammersperspective,isErland'sCurseandBlessingsofDynamicSQL.The DynamicSQLapproachescanbedevelopedbasedoncreatingaTransactSQLquerystringbasedonthenumber of groups and then use a series of CASE expressions or ROW_NUMBER() function to pivot the data for concatenation.
DCAE@ACA(A)nITiIT ELRrVRHRMX,@N,@N SLCi=1 EET@, r='EETCtgrI,'+CA(3, @SLCaeoydHR1) n=(EETTP1CUTrdcNm @SLCOON(Poutae) RMNrhid.rdcs FOotwn.Pout GOPBaeoyd RUYCtgrI ODRBON(Poutae)DS REYCUTrdcNmEC) WIE@=@EI HLi<nBGN Er=@ ST@r+ AEWEi=1 CSHN@ TEMXAESqWEATiAACA HN'A(CSeHN'+CS(@SVRHR)+' HNPoutae TErdcNm ESPC()ED)+'+CA(3 LESAE0NHR1) HN@n WEi=@ HN'A(CSeHN'+CS(@SVRHR)+' TEMXAESqWEATiAACA

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

6/22

04/04/12

Concatenating Row Values in Transact-SQL


HN','rdcNm TE''+Poutae LESAE0NHR1) ESPC()ED)'+CA(3 LE'A(CSeHN'+CS(@SVRHR)+' ESMXAESqWEATiAACA HN','rdcNm TE''+Poutae LESAE0NHR1) ESPC()ED)+'+CA(3 N ED Ei=@ ST@i+1 ED N ST@r+' Er=@ FOEETCtgrI,Poutae RM(SLCaeoydrdcNm, RWNME(VR(PRIINBaeoydODRBrdcNm O_UBR)OEATTOYCtgrIREYPoutae) RMNrhid.rdcsp)D(CtgrI,Poutaee FOotwn.PoutaeoydrdcNm,Sq) RUYCtgrI GOPBaeoyd' EE(@ XCr)

TheCursorapproach
ThedrawbacksoframpantusageofcursorsarewellknownamongtheTransactSQLcommunity.Becausetheyare generallyresourceintensive,proceduralandinefficient,oneshouldstrivetoavoidcursorsorloopbasedsolutions ingeneralTransactSQLprogramming.
DCAE@bALiNRMRE,lsACA(00) ELRtlTBE(dITPIAYKYitVRHR80) STNCUTO EOONN DCAE@N,@ACA(00,@NxN,@NxACA(0 ELRcITpVRHR80)cetITpetVRHR4) DCAEcCROO ELRUSRFR SLCaeoydrdcNm EETCtgrI,Poutae FOotwn.Pout RMNrhid.rdcs REYCtgrI,Poutae ODRBaeoydrdcNm OE PNc FTHNXRMcITcetpet ECETFONO@Nx,@Nx ST@cet Ec=@Nx WIE@FTHSAUEI HL@EC_TTS=0BGN F@NxcBGN Icet>@EI ISRtlSLCcp NET@bEET@,@ SLCp=@Nx,@cet EET@Petc=@Nx NLE EDES ST@OLSE@,,SAE0)+@Nx Ep=CAEC(p+''PC()pet ECETFONO@Nx,@Nx FTHNXRMcITcetpet ED N ISRtlSLCcp NET@bEET@,@ COEc LS DALCT ELOAEc SLCRM@b EET*FOtl

Unreliableapproaches
This section details a couple of notorious methods often publicized by some in public forums. The problem with thesemethodsisthattheyrelyonthephysicalimplementationmodelchangesinindexes,statisticsetcorevena change of a simple expression in the SELECT list or ORDER BY clause can change the output. Also these are undocumented,unsupportedandunreliabletothepointwhereonecanconsistentlydemonstratefailures.Therefore thesemethodsarenotrecommendedatallforproductionmodesystems.

ScalarUDFwithtSQLupdateextension
Itisrarefortheusageofanexpressionthatinvolvesacolumn,avariableandanexpressionintheSETclauseinan UPDATEstatementtoappearintuitive.However,ingeneral,theoptimizeroftenseemstoprocessthesevaluesin theorderofmaterialization,eitherintheinternalworktablesoranyotherstoragestructures.
CETUCINufudt_oct(CtgrIN) RAEFNTOd_paecna@aeoydIT RTRSVRHRMXS EUNACA(A)A BGN EI DCAE@AL(ACA(0) ELRtTBEpVRHR4) DCAE@ACA(A) ELRrVRHRMX ST@PC() Er=SAE0 ISRt(p)SLCrdcNmRMNrhid.rdcs NET@EETPoutaeFOotwn.Pout HRaeoyd=@aeoyd WEECtgrICtgrI I@OCUT>0 F@RWON UDTt PAE@ Er=@, ST@r+p+'' RTR(r EUN@) ED N

Hereishowtousethisfunction:
SLCaeoydb.d_paecna(aeoyd EETCtgrI,doufudt_octCtgrI) FOotwn.Pout RMNrhid.rdcs RUYCtgrI GOPBaeoyd

Again,itisimportanttoconsiderthatlackofphysicalindependencethatisbeingexploitedherebeforeusingor

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

7/22

04/04/12

Concatenating Row Values in Transact-SQL

recommendingthisasausableandmeaningfulsolution.

ScalarUDFwithvariableconcatenationinSELECT
Thisisanapproachpurelydependentonthephysicalimplementationandinternalaccesspaths.Beforeusingthis approach,makesuretorefertotherelevantknowledgebasearticle.
CETUCINdoufslc_oct(@N RAEFNTOb.d_eetcnacIT) RTRSVRHRMXSBGN EUNACA(A)AEI DCAE@ACA(A) ELRpVRHRMX Ep=' ST@' SLCp=@rdcNm, EET@p+Poutae+'' FOotwn.Pout RMNrhid.rdcs HRaeoyd=@ WEECtgrIc RTRp EUN@ ED N

And,asforitsusage:
SLCaeoydb.d_eetcna(CtgrI EETCtgrI,doufslc_octaeoyd) FOotwn.Pout RMNrhid.rdcs RUYCtgrI GOPBaeoyd

Conclusion
Regardlessofhowitisused,"aggregateconcatenation"ofrowvaluesinTransactSQL,especiallywhenthereisa grouping,isnotasimpleroutine.Youneedtoconsidercarefullythecircumstancesbeforeyouchooseonemethod overanother.Themostlogicalchoicewouldtohaveabuiltinoperatorwithoptionalconfigurableparametersthat candotheconcatenationofthevaluesdependingonthetype.Tillthen,reportingrequirementsandexternaldata exportroutineswillhavetorelyonsuchTransactSQLprogramminghacks.

References
PRB:ExecutionPlanandResultsofAggregateConcatenationQueriesDependUponExpressionLocation NorthwindandpubsSampleDatabasesforSQLServer2000 TheCurseandBlessingsofDynamicSQL IntroductiontoCommonLanguageRuntime(CLR)Integration

Acknowledgements
Umachandar Jayachandran, Linda Wierzbecki, Bruce Margolin, Roy Harvey, Eugene Kogan, Vadim Tropashko, AnubPhilip. AdditionalinformationabouttheXMLBlackboxapproachinserted22/03/2012.

Thisarticlehasbeenviewed308671times.

Authorprofile:AnithSen AnithSLarsonspecializesindatamanagementprimarilyusingSQLServer.Fromthemid90s,he hasbeenworkingonavarietyofdatabasedesignandsystemsdevelopmentprojectsforclients primarilyinwealthmanagementandfinancialservicesindustry.HeresidesinLakeland,TN. SearchforotherarticlesbyAnithSen

Ratethisarticle:Avgrating:
Poor OK Good

fromatotalof346votes.
Great Mustread

HaveYourSay
Doyouhaveanopiniononthisarticle?Thenaddyourcommentbelow:

Youmustbeloggedintoposttothisforum Clickheretologin.
Subject: Postedby: Postedon: Message: MySolution DaveTheWave(viewprofile) Thursday,July31,2008at3:49PM Iusethefollowing.Thisisnotcompletelymycode.Ifoundmostif

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

8/22

04/04/12
notnearlyallofthisonthenet.

Concatenating Row Values in Transact-SQL


CETALaaeeKy RAETBEPrmtres ( PrmtreNDNIY aaeeKyITIETT RMRE, PIAYKY DtCetdDTTMOUL aeraeAEIENTNL ) CETALaa_octnto RAETBEPrmCnaeain ( PrmtreNEEECSPrmtres aaeeKyITRFRNEaaeeKy (aaeeKy Prmtre) NDLTACD, OEEECSAE VleeACA(0OUL auKyVRHR5)NTNL, VleuKyACA(0UL auSbe1VRHR5)NL, VleuKyACA(0UL auSbe2VRHR5)NL, VleVRHR5)NTNL auACA(0OUL ) G O CETRCDRaa_eKy RAEPOEUEPrmGte PrmtreNUPT @aaeeKyITOTU A S EEEFOaaeeKy DLTRMPrmtres HRDtCetd<DTADDY7EDT() WEEaeraeAED(A,,GTAE) NETITaaeeKy ISRNOPrmtres (aerae) DtCetd AUS(EDT() VLEGTAE) EPrmtreCP_DNIY) ST@aaeeKy=SOEIETT( G O CETRCDRaa_eeeePrmtreN RAEPOEUEPrmDltKy@aaeeKyIT A S EEEFOaaeeKy DLTRMPrmtres HRPrmtrePrmtre WEEaaeeKy=@aaeeKy G O CETUCINf_octnt RAEFNTOnCnaeae ( @aaeeKyIT PrmtreN, @auKyVRHR5) VleeACA(0, @auSbe1VRHR5) VleuKyACA(0, @auSbe2VRHR5) VleuKyACA(0, @eiieACA(0 DlmtrVRHR5) ) RTRSVRHR80) EUNACA(00 AEI SBGN DCAE@epalALvleVRHR5) ELRtmTbeTBE(auACA(0) DCAE@eutVRHR80) ELRrslACA(00 ST@eut='lcHleDmyet ErslPaeodrumTx' ISRtmTbe NET@epal EETVle SLCau RMPrmCnaeain FOaa_octnto HRPrmtrePrmtre WEEaaeeKy=@aaeeKy ADVleeVlee NauKy=@auKy ADVleuKyVleuKy NauSbe1=@auSbe1 ADVleuKyVleuKy NauSbe2=@auSbe2 REYVleAC ODRBauS I@OCUT>0 F@RWON PAE@epal UDTtmTbe E@eut=@eut+@eiie STrslrslDlmtr+''+ vle au RTRRPAE EUN(ELC( ELC(rsl,'lcHleDmyet, RPAE@eutPaeodrumTx,' ') ', PaeodrumTx' 'lcHleDmyet, ') ' ) N ED /* * UAE SG IhRESEALtbecnanholwnaa fteODRDTIalotistefloigdt: ODRDFO_YEFO_O. REIRMTPRMCL.. .. . 678916 54958 678983 54950 678984 54950 678986 54950 678988 54950 678981 54951 678982 54951 678996 54991 678999 54991 678990 54992 405916 45958 405983 45950 405984 45950 405985 45950 405986 45950

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

9/22

04/04/12
405988 45950 405989 45950 405980 45951 405981 45951 405982 45951 .. . * /

Concatenating Row Values in Transact-SQL

DCAE@aaeeKyIT ELRPrmtreN EEb.aa_eKy@aaeeKyOTU XCdoPrmGtePrmtreUPT ISRNOPrmCnaeain NETITaa_octnto SLCITNT EETDSIC aaeeKy=@aaeeKy PrmtrePrmtre, auKy=o.REI, VleedODRD auSbe1='RMTP' VleuKyFO_YE, auSbe2='' VleuKyx, audFO_O Vle=o.RMCL RMODRDTId FORESEALo HRdODRDI'54''45' WEEo.REIN(678,405) SLCb.nCnaeae@aaeeKy EETdof_octnt(Prmtre, 678, '54' FO_YE, 'RMTP' x, '' ,) '' SLCb.nCnaeae@aaeeKy EETdof_octnt(Prmtre, 405, '45' FO_YE, 'RMTP' x, '' ,) '' Wudpouttefloigotu olrdcholwnupt Odr678wudrslswle re54oleutilb: 168384868881829699 58,50,50,50,50,51,51,91,91, 92 90 Odr405wudrslswle re45oleutilb: 168384858688898081 58,50,50,50,50,50,50,51,51, 51 82

Subject: Postedby: Postedon: Message:

Ooh!Thislooksfun PhilFactor(viewprofile) Thursday,July31,2008at4:16PM Hereismymethod.ItworksinbothSQLServer2000and2005. Goodnessme,Anith,you'regoingtohateit.


DCAE@cuuainVRHR70) ELRacmltoACA(00, vralsdfracmltnit aibeueocuuaiglss @aeoyDIT CtgrIN vralsdfrkeigtbnteGOPNd aibeueoepnasohRUIGi DCAE@ruigTBEeprral ELRgopnALtmoaytbe ( yDITIETT(,1RMRE, MINDNIY1)PIAYKY aeoyDIT CtgrIN, rdcNmACA(5) PoutaeVRHR25, cuuainVRHR70)sdtolchit acmltoACA(00ueoclettels ) ISRNO@ruigisraeutyuwn NETITGopnnetrwrsloata GOPNf RUIGo (aeoyDrdcNm) CtgrI,Poutae EETCtgrI,Poutae SLCaeoyDrdcNm RMNrhid.rdcs FOotwn.Pout REYCtgrI,Poutae ODRBaeoyDrdcNm UDTgopnnpaetetbeonh PAE@ruigadudthal,digte acmlto. cuuain EAcmltoacmlto] ST@cuuain=[cuuain OLSE =CAEC( AEWEaeoyD< CSHNCtgrI> CAEC(CtgrI,0 OLSE@aeoyD) HN'rdcNm TE'+poutae LELF(Acmlto, ESET@cuuain+''+ poutae00 rdcNm,70) N, ED ', ') CtgrIaeoyD @aeoyD=CtgrI SLCaeoyDA(cuuain EETCtgrI,MXacmlto) RM@ruig FOgopn RUYCtgrI GOPBaeoyD REYCtgrI ODRBaeoyD

Subject: Postedby: Postedon: Message:

CLRmethods AdamMachanic(viewprofile) Friday,August01,2008at9:09AM Nicetoseeyouhere,Anith! RegardingtheCLRmethod,ifyou'renotafraidtoworkwithsomein memorystructuresyoucanbothgreatlyimproveperformanceand

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

10/22

04/04/12

Concatenating Row Values in Transact-SQL


exceedthe8000bytebarrier.IsuspectthatFORXMLPATHwillstill deliverbetterperformanceinmanycases,though. OnecaveatofFORXMLPATHmethodistheissueof"entitization." Trythefollowing:
SLC EET n+''Atx(] ,S[et) FO RM ( SLCabSn EET'<'A UINAL NOL SLCba EET'>' )r FRXLPT(' OMAH') .. .

TOfixthisproblemweneedtoplaysomeratherannoyinggames:
SLC EET ( SLC EET ( SLC EET n+''Atx(] ,S[et) FO RM ( SLCabSn EET'<'A UINAL NOL SLCba EET'>' )r FRXLPT(',TP OMAH')YE )Aoct Scna FRXLRWYE OMA,TP )vle'rw1/oct1'vrhrmx' .au(/o[]cna[],'aca(a))

<plug> IwroteabouttheCLRmethodindetailin"ExpertSQLServer2005 Development"(Apress,2007) </plug>

Subject: Postedby: Postedon: Message:

Re:Ooh!Thislooksfun AnithSen(notsignedin) Friday,August01,2008at9:31AM Goodjob,Phil. Sinceyouareusingatablevariableyouhavecontroloverthe underlyingindexesandsoyoudon'thavetoworryaboutsomebody elsechangingthemandaffectingtheoutput. Inevercompletelyunderstoodtheunderlyingevaluationschemeint SQLUPDATEEXTENSION.Isitrighttoleft,allatonce,random,I havenoidea.Regardless,itseemstoworkfinehere. AnotherconcernistheINSERT..SELECTstatementwithan ORDERBYclause.Again,inthiscase,sinceyouareusingatable variableitseemslikethereshouldn'tbeanyproblems.Therehas beenseveralonlinediscussions(forinstance, http://tinyurl.com/67yovl)andIbelievetheconsensusnowisthatit shouldworkasexpected.

Subject: Postedby: Postedon: Message:

Re:CLRmethods AnithSen(notsignedin) Friday,August01,2008at10:18AM HelloAdam, Thatisanexcellentpoint.RatherthanusingREPLACEfunction,itis bettertohavethevaluemethodofthexmltype.Oneissueseemsto be,asyousaid,the"annoyinggames"withmultiplelevelsof derivation.Iamnotcompletedsurehowtoproceedwhenthereisa groupingcolumnDoyouincludethegroupedcolumnasanelement inyourxmlvaluelike:
SLCaeoydrdcs EETctgri,Pout FOEETp.aeoyd RM(SLC1CtgrI, EETPoutae+'' (SLCrdcNm, RMNrhiddoPout2 FOotwn.b.rdcsp WEEp.aeoyd=p.aeoyd HR2CtgrI1CtgrI ODRBrdcNm REYPoutae FRXLPT(',TP,EEET, OMAH')YELMNS OT(poutae))SPout RO'rdcnm'Ardcs FOotwn.b.rdcsp RMNrhiddoPout1 GOPBaeoyd)AitFRXLRWYE RUYCtgrISlsOMA,TP

Thanks

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

11/22

04/04/12
Subject: Postedby: Postedon: Message:

Concatenating Row Values in Transact-SQL


grouping AdamMachanic(viewprofile) Friday,August01,2008at1:41PM Agreed,groupingisaproblem,butnotjustwithXMLvirtuallyallof thesesolutions(exceptthecursorandCLRUDA)havequiteabitof unnecessaryoverheadbecausetheenginedoesn'tsupportthisstuff. Regardingcursors,yetanotheroptionisaCLRstoredprocedure. YoucanreadthedatawithSqlDataReader,dotheconcatenation withStringBuilder,andsendalloftheresultsbacktothecallerina singlerowsetratherthanstuffingthemintoatemptable.Much, muchmoreefficientthanaTSQLcursor.

Subject: Postedby: Postedon: Message: Subject: Postedby: Postedon: Message:

Goodarticle PedroJ(notsignedin) Saturday,August02,2008at12:19AM Thisisausefularticle.Somemethodsareverynewtome. Greatarticle Anonymous(notsignedin) Thursday,August07,2008at2:28AM RecursiveCTEmethodsisbithardtounderstand

Subject: Hereisanotherwayofdoingit Postedby: PhilFactor(viewprofile) Postedon: Thursday,August07,2008at8:56AM Message: ThismethodworksinSQLServer2000upwards.Asyou'llsee,itgoes aboutitquiteadifferent,slightlycheating,way.AsfarasIknow,Robyn andIinventedit,thoughittookthreecupsofcoffee.
DCAE@itVRHRMX ELRlsACA(A) SLCLs=OLSE@it''') EET@itCAEC(ls+,,' ''CNETVRHR5,aeoyD +|+OVR(ACA()CtgrI) ''rdcNm+|+OVR(ACA()CtgrI)+| +|+poutae''CNETVRHR5,aeoyD'' FOotwn.poutREYctgrI,rdcNm RMnrhid.rdcsODRBaeoyDpoutae SLCAEOYd EETCTGRi, Pout [rdc Ls]LF(ebr,HRNE(,'mmes'|)1RM it=ETmmesCAIDX'|,ebr+,')FO ( SLCaeoyDmmes= EETctgrI,'ebr' RPAE ELC( SBTIGls, USRN(it CAIDX''CNETVRHR5,aeoyD+|,it,00, HRNE(|+OVR(ACA()CtgrI)''ls)80) |+OVR(ACA()CtgrI)''' ''CNETVRHR5,aeoyD+|,') FOSLCls'@itf RM(EET'it=Ls) COSJI RSON( EETctgrIRMnrhid.rdcsGOPB SLCaeoyDFOotwn.poutRUY ctgrI aeoyD Ctgre )aeois ) g

Subject: Postedby: Postedon: Message:

anotherapproach... rudy(notsignedin) Thursday,August07,2008at10:31AM [code]SELECTCategoryId ,GROUP_CONCAT(ProductName)ASProductList FROMNorthwind..Products GROUP BYCategoryId[/code] oh,wait,thishowyoudoitinMySQL stupidopensoresdatabases,makingthingseasy!!! o)

Subject: Postedby: Postedon: Message: Subject: Postedby: Postedon: Message:

Re:anotherapproach... AdamMachanic(viewprofile) Thursday,August07,2008at2:40PM Opensores?SoundslikeaproductI'dratheravoid. ExcellentArticle TimothyAWiseman(notsignedin) Thursday,August07,2008at4:52PM ExcellentarticleandithadsometechniquesIhadneverconsidered before. JeffModenapproachedthesametopicfromapurelyperformance standpointin: http://www.sqlservercentral.com/articles/Test+Data/61572/ AndsomeoftheCTEportionissimilarto http://www.sqlservercentral.com/articles/CTE/62404/thoughthat

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

12/22

04/04/12
focusesonreadability.

Concatenating Row Values in Transact-SQL

Anith,yourarticlewasextremelythoroughandenlightening. Subject: Postedby: Postedon: Message: Re:Hereisanotherwayofdoingit AnithSen(notsignedin) Monday,August11,2008at1:03PM Thatisanewone,Phil.Andagoodone:)Iseeyoubuildthe"big" listandthensplititup. Question,whathappensifIchangetheORDERBYclauseasthe followingandwhy? ORDERBYLEFT(categoryID,5),productName Subject: Postedby: Postedon: Message: Subject: Postedby: Postedon: Message: Re:ExcellentArticle AnithSen(notsignedin) Monday,August11,2008at1:10PM Thanksforthelinks,Timothy.Andforthosecommentsaswell:) Re::Hereisanotherwayofdoingit PhilFactor(viewprofile) Monday,August11,2008at2:01PM Simpleconcatenationisn'talwaysreliable.Therearecircumstances whereitsimplydoesn'thappen.Thiscanvaryfromonereleaseof SQLServertoanother.Isometimeswishthey'dtieitdown!Inthe caseyoumention,thereisnosupportedorderfortheconcatenation tooccur.TheuseofanexpressionintheORDERBYforcesa differentexecutionplanwhichproducesanindeterminateorderfor theconcatenation,presumablybecausetheorderbyispostponed untilaftertheconcatenationisperformed. Iwasbroughtuptobelievethatthe'orderby'parametershould alwaysbeoneofthoseintheresultset.I'mnotsureifthatwould helpiftheorderbyparameterwastheresultofafunction. MyownexperienceisthatasimpleSQL92querywillresultina correctconcatenation.The'Sybase'updatewillalsousuallywork reliably,butoccasionallyneedsa'tickle'.Ifyoupileinwiththefancy stuff,yourunariskthattheconcatenationendsupwithmerelythe laststringaddedtoit. Thanksforafascinatingarticle.Ithascertainlytaughtmeseveral things. Subject: Postedby: Postedon: Message: Subject: Postedby: Postedon: Message: Excellentarticle PrashanthKumar(notsignedin) Tuesday,August12,2008at4:16AM Thisisanexcellentarticle. JoinandSplit mjswart(viewprofile) Wednesday,August13,2008at8:18AM AverythorougharticleonJoining/Concatenatingstrings. http://dbwhisperer.blogspot.com/2008/06/splittingandjoiningstrings insql.htmlmentionsjoining(usingxmlpathsyntax)anditalsotalks abouttheinversetaskofsplitting. SplittingacommaseparatedvaluesisacommontaskIthink. Hopefullyitwillbecomelesscommonwithtablevaluedparameters. Subject: Postedby: Postedon: Message: re:Joinandsplit PhilFactor(viewprofile) Wednesday,August13,2008at9:10AM http://www.simpletalk.com/sql/tsqlprogramming/thehelpertable workbench/mightgiveyouafewmoreideasonthetopicofsplitting andjoiningstrings.Thisarticlereallyismoreabouttheproblemof producingalistofdistinguishingcolumnsofallrowsthataregrouped togetherbyeachuniquevalueina'Groupby'inSQLServer,using concatenation.I'vehearditcalled'Theindexers'grouping. join Anonymous(notsignedin) Friday,August22,2008at5:25AM ALTERfunction[dbo].[GetBillStandardFeatures]( @UnitIDint, @IsStandardbit ) returnsvarchar(6000) as begin declare@strnvarchar(4000) declare@nmvarchar(50) declare@tempvarchar(100)

Subject: Postedby: Postedon: Message:

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

13/22

04/04/12
set@str=''

Concatenating Row Values in Transact-SQL

DECLARERuleListCURSORFOR selectFeatureIDfromtblUnitFeaturewhereUnitID=@UnitID OPENRuleList FETCHNEXTFROMRuleListinto@nm WHILE(@@FETCH_STATUS=0) begin set@temp='' select@temp=NamefromtblFeaturewhereFeatureIDin(@nm) andIsStandard=@IsStandard if@temp<>'' begin set@str=@str+@temp+'<br/>' end FETCHNEXTFROMRuleListinto@nm end CLOSERuleList DEALLOCATERuleList return@str end iamusingthiswayinthisipasstheidfromtheoutsideandthey joinwith"br"andreturnthestring vipul Cybercomcreation(Ahemdabad) dongavipul@gmail.com http://dongavipul.blogspot.com Subject: Postedby: Postedon: Message: Recursionandrowpairing CaryHower(notsignedin) Friday,August22,2008at9:20AM declare@ttable (CatIDtinyintidentity(1,1)primarykey ,CategoryIDtinyintnotnull ,ProductNamevarchar(4000)notnull ) declare@Incrtinyint ,@Rowstinyint insertinto@t(CategoryID,ProductName) selectCategoryID ,ProductName fromProducts orderbyCategoryID ,ProductName select@Rows=@@RowCount select@Incr=1 while@Rows>0 begin updatel setProductName=l.ProductName+','+r.ProductName from@tl join@tr onl.CategoryID=r.CategoryID andl.CatID+@Incr=r.CatID and(l.CatID(selectmin(CatID)from@twhereCategoryID= l.CategoryID))%(@Incr*2)=0 select@Rows=@@RowCount deletel from@tl where(CatID(selectmin(CatID)from@twhereCategoryID= l.CategoryID))%(@Incr*2)=case@Incrwhen1then1else@Incr end select@Incr=@Incr*2 end Afunctioncanbecreatedthatreturns@twithouttheidentity column Subject: Postedby: Postedon: Message: Recursionandrowpairing(correction) CaryHower(notsignedin) Friday,August22,2008at9:23AM Iapologizeforanoversight.Thedeletestatmentcasewas unnecessary."case@Incrwhen1then1else@Incrend"should havebeensimply"@Incr"

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

14/22

04/04/12
Subject: Postedby: Postedon: Message:

Concatenating Row Values in Transact-SQL


Recursionandrowpairing(correction) CaryHower(notsignedin) Friday,August22,2008at9:25AM Iapologizeforanoversight.Thedeletestatmentcasewas unnecessary."case@Incrwhen1then1else@Incrend"should havebeensimply"@Incr" Newbie'sconsideration MarzioAlunni(viewprofile) Friday,August22,2008at5:25PM Hi,IhavelittleexperiencewithSQLserverandIknowalmostnothing aboutCLRbutreadingthisarticleInoticedthatonlytheCLRmethod letencapsulatetheconcatenationlogicinaseparatefunction. Itseemstomeabigpro. Theresultingqueryhavefarmoregraterreadability,andavoidthe overheadimposedbytheothermethods. I'monlyconcernedaboutperformance...Youthinkthisis unmotivated,andduetomyignoranceoftheCLRsubject? Thanks(IApologizeformypoorEnglish...P)

Subject: Postedby: Postedon: Message:

Subject: Postedby: Postedon: Message:

ShamassaeedConsidration Shamassaeed(notsignedin) Sunday,August24,2008at11:11PM Thisisgoodarticle.Youcanshowrowvaluesinonecolumnusing, seperatedoranyothercharacter.Thisisgoodforextraknowledge butonethingmustmentionthewecanconcatethesevaluesin anotherwayandiamdoingthisfromyear'sbefore. Wecanusecoleascefunctiontodothisas. Select@vProductName=COALESCE(@vProductName+',','')+ ProductNamefromProduct Declare@vProductNameavariableandreturnselectresultin, seperatedvalues.

Subject: Postedby: Postedon: Message:

Re:Newbie'sconsideration AnithSen(notsignedin) Monday,August25,2008at1:11PM Marzio, Asfarasseparatingtheconcatenationlogic,tSQLUDFsshoulddo itjustfine.Iamnotfamiliarwiththeperformancefactorsrelatedto CLR.Perhaps,someoneelsemaychimein, Anith

Subject: Postedby: Postedon: Message:

Re:ShamassaeedConsidration AnithSen(notsignedin) Monday,August25,2008at1:15PM Shamas, Themethodyousuggestedhassomeissuesitcanbe unpredictableeveninsomecases,doesn'treturnanyrows.I mentioneditinthearticleunderthesection"Unreliableapproaches". Youcanfindseveralexamplesoffailurediscussedinthearchivesof googlegroups. Anith

Subject: Postedby: Postedon: Message:

Re:Re:Newbie'sconsideration MarzioAlunni(viewprofile) Wednesday,August27,2008at5:58AM Sorry,Iwasnotclear. WhenIwrote"onlytheCLRmethodletencapsulatethe concatenationlogicinaseparatefunction",Imeantinawaycould byeasilyreusedforeveryquerythatneedconcatenation. Aswecanseefromyourexamples,withUDFIcanencapsulate concatenationlogicforaspecificcolumnofaspecifictable,soifI needtoconcatenateanothercolumnfromanothertableIhaveto writeanotherUDF. DoyouthinkitsagoodargumenttopreferCLRaggregateonother options? Marzio

Subject: Postedby: Postedon: Message:

Re:Re:Newbie'sconsideration MarzioAlunni(viewprofile) Wednesday,August27,2008at5:59AM Sorry,Iwasnotclear. WhenIwrote"onlytheCLRmethodletencapsulatethe concatenationlogicinaseparatefunction",Imeantinawaycould byeasilyreusedforeveryquerythatneedconcatenation. Aswecanseefromyourexamples,withUDFIcanencapsulate concatenationlogicforaspecificcolumnofaspecifictable,soifI needtoconcatenateanothercolumnfromanothertableIhaveto writeanotherUDF.

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

15/22

04/04/12

Concatenating Row Values in Transact-SQL


DoyouthinkitsagoodargumenttopreferCLRaggregateonother options? Marzio

Subject: Postedby: Postedon: Message:

newsolution niko_san(notsignedin) Tuesday,September02,2008at7:43AM SELECTCategoryId,CAST(ProductNameasnvarchar(max))as ProductNameinto#ProductsfromNorthwind..Products orderbyCategoryId,ProductName declare@StringIDnvarchar(max) declare@StringDatanvarchar(max) SET@StringData='' SET@StringID='' UPDATE#Products SET @StringData=CASEWHENCategoryId=@StringID THEN@StringData+ProductName+',' ELSEProductName+','END, @StringID=CategoryId, ProductName=CASEWHENCategoryId=@StringID THEN@StringData ELSEProductNameEND select CategoryId,substring(max(ProductName),1,len(max(ProductName))1) from#Products groupbyCategoryId droptable#Products

Subject: Postedby: Postedon: Message:

newsolution niko_san(notsignedin) Tuesday,September02,2008at8:19AM SELECTCategoryId,CAST(ProductNameasnvarchar(max))as ProductNameinto#ProductsfromNorthwind..Products orderbyCategoryId,ProductName declare@StringIDnvarchar(max) declare@StringDatanvarchar(max) SET@StringData='' SET@StringID='' UPDATE#Products SET @StringData=CASEWHENCategoryId=@StringID THEN@StringData+ProductName+',' ELSEProductName+','END, @StringID=CategoryId, ProductName=CASEWHENCategoryId=@StringID THEN@StringData ELSEProductNameEND select CategoryId,substring(max(ProductName),1,len(max(ProductName))1) from#Products groupbyCategoryId droptable#Products

Subject: Postedby: Postedon: Message:

sybaselist jengo(notsignedin) Thursday,September18,2008at7:25PM table: idname 1test 2again 1work 2better sybasesqlstring: selectid,list(name)fromtable_namegroupbyid result: idlist(name) 1test,work 2again,better

Subject: Postedby: Postedon: Message: Subject: Postedby:

Goodone Murali(viewprofile) Tuesday,October28,2008at3:54PM Ihavelearntlotofthingsfromthisartical. lengthlimit Chi(notsignedin)

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

16/22

04/04/12
Postedon: Message:

Concatenating Row Values in Transact-SQL


Thursday,October30,2008at2:49PM Itworkswellandisanelegantsolution,butwhentheresultismore 255,therestiscutoff.Anyideahowtoworkaroundthis? Thanks!

Subject: Postedby: Postedon: Message: Subject: Postedby: Postedon: Message:

Re:lengthlimit Chi(notsignedin) Thursday,October30,2008at2:52PM (IwasreferringtotheForXMLPathapproach) AnonymousCommentingDisabled ChrisMassey(viewprofile) Monday,November10,2008at5:53AM Anonymouscommentinghasbeendisabledinthisarticledueto spamming.Ifyouwanttoaddyourcomments,I'mafraidyou'lleither needtotosigninorsignup.Sorryfortheinconvenience. KickMe Lee(viewprofile) Thursday,December18,2008at12:06PM Fine,I'llpaintthetargetonmyTshirtonthisone:Ihavebeenusing the"unreliable"stringconcatenationtechnique"ScalarUDFwith variableconcatenationinSELECT"sinceIstartedoutdoing Sybasein1991.Yearsbefore,Imightadd,peoplebeganhaving heartmurmursoverthistechnique.Overandover,Ihavebeen lecturedonits"unreliability",butinseventeenyears,Ihavenever seenitbreak. But...pointtaken.Itisagoodpolicynottoreleasecodethatrelies onanunsupportedbehavior.Idonotthinkitwouldbeeasyfor Microsofttobreakthatparticularbehaviortheywouldhaveto changeortakeawayaltogethertheabilitytosetaVARCHARlocal variablewithaSELECT,andphysicallydosomethingtokeepthe impliedloopintheSELECTfromrunning.Butthat'sreallybesidethe point.Thanksforagoodarticle.

Subject: Postedby: Postedon: Message:

Subject: Postedby: Postedon: Message:

CLRError DBowlerHB(viewprofile) Wednesday,February25,2009at12:58PM GreatarticalAnith!!IreallylikedtheideaofusingCLRtoaddthis functionsoitcouldbereusedeasily.Itriedtocreatethenew strConcatfunctionusingyourexamplewordforwordunfortunatlyI'm gettinganerrorwhenIbuildthesolution. Ontheline: "privateSystem.Collections.Generic.Listvalues" Theword"List"isunderlinedwiththefollowingerror: "Usingthegernerictype'System.Collections.Gerneric.List<T>' requires'1'typearguments." BecauseIamverynewtoC#Idonotknowhowtofixthisissue, andthoughtIwouldnotifyyouthatyoursamplemayhavea problem. Anyideas? ~DB

Subject: Postedby: Postedon: Message:

StringConcatenationChallenge/Contest AdamMachanic(viewprofile) Friday,February27,2009at12:31PM Enjoyedthisarticle? Good,nowgotrytosolveaTSQLstringconcatenationchallenge andwinaprize: http://sqlblog.com/blogs/adam_machanic/archive/2009/02/27/tsql challengegroupedstringconcatenation.aspx :)

Subject: Postedby: Postedon: Message:

Re:ShamassaeedConsidration Dennis(viewprofile) Sunday,March01,2009at1:44PM LikeLee,Iusethismethodalot.Iacceptthattheorderofitemsin theconcatenatedlistisnotreliable.Itdoesn'tevenmakesenseto OrderByonacolumnthatcouldn'tlogicallybepresentintheresult set. Asidefromthat,Idon'tunderstandanypurporteddependencyon physicalimplementation,indexingorthelike. Cananybodyexplainthatorgiveatestcasewherethe concatenationmethoddoesn'twork?

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

17/22

04/04/12
Subject: Postedby: Postedon: Message:

Concatenating Row Values in Transact-SQL


Actually,variableconcatenationinSELECTisReliable RBarryYoung(viewprofile) Sunday,March01,2009at1:47PM ForSQLServer2005atleast,itisnotcorrecttosaythatvariable concatenationinSELECTiseitherunreliableordependentonthe physicalimplementation.Theexamplegivenisunreliablebecauseit hasanerrorinthatitlacksanORDERBYclausetoinsurethe properordering.Hereisacorrectimplementation: CREATEFUNCTIONdbo.udf_select_concat(@cINT) RETURNSVARCHAR(MAX)ASBEGIN DECLARE@pVARCHAR(MAX) SET@p='' SELECT@p=@p+ProductName+',' FROMNorthwind..Products WHERECategoryId=@c ORDERBYProductName RETURN@p END ThisisalldocumentedandsupportedstraightoutofBOL.Finally, thereferencedknowledgebasearticleisnotrelevantbecauseitis onlyforSQLServer2000and7.0.

Subject: Postedby: Postedon: Message:

Re:ShamassaeedConsidration Dennis(viewprofile) Sunday,March01,2009at6:32PM LikeLee,Iusethismethodalot.Iacceptthattheorderofitemsin theconcatenatedlistisnotreliable.Itdoesn'tevenmakesenseto OrderByonacolumnthatcouldn'tlogicallybepresentintheresult set. Asidefromthat,Idon'tunderstandanypurporteddependencyon physicalimplementation,indexingorthelike. Cananybodyexplainthatorgiveatestcasewherethe concatenationmethoddoesn'twork?

Subject: VariableconcatenationinSELECT Posted Anith(viewprofile) by: Posted Wednesday,April01,2009at3:26PM on: Message:RBarryYoungandDennis, Thereareseveralcaseswhereitfails.SeveralforummembersinMicrosoftnewsgroupshave postedseveralexamples,atleastfromversion7.0onwards.Forsomeexamples,see: http://groups.google.com/group/microsoft.public.sqlserver.programming/msg/70917b5ca789ea77? dmode=source http://groups.google.com/group/microsoft.public.sqlserver.programming/msg/371167d94545e1d7? hl=en&dmode=source Theproblemisseveralpeopleignorethesewarningsandkeepusingthemonlytofindonedayit suddenlystoppedworking! Anith Subject: Postedby: Postedon: Message: MuchSimplerWay StephanKoch(viewprofile) Monday,July13,2009at4:41PM HiAnith ThisishowIdoit.Notsurewhynobodyelsesemstodoitthisway: Initialisevariables DECLARE@valuesvarchar(MAX) set@values='' Getthestring Select@values=@values+'['+ProductName+'],'from Northwind..products Stripoutthelastcomma select@values=left(@values,len(@values)1) Print@values Thiscodeisnotentirelycomplete,sinceitwillfalloverwhenthere arenorowsintheproducttable,butyougettheidea. IusethisapproachtobuildvaluesforvariablePIVOTclauses. Subject: Postedby: Postedon: Muchsimplerwaypart2 StephanKoch(viewprofile) Monday,July13,2009at5:10PM

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

18/22

04/04/12
Message: Subject: Postedby: Postedon: Message:

Concatenating Row Values in Transact-SQL


OopsjustrealisedthatIwassolvingadifferentproblemmineonly worksforasinglegroupatatime...sorryforconfusion. Muchsimplerwaypart2 StephanKoch(viewprofile) Monday,July13,2009at5:50PM OopsjustrealisedthatIwassolvingadifferentproblemmineonly worksforasinglegroupatatime...sorryforconfusion. AnubPhilip'smethod GeoffS(viewprofile) Monday,August03,2009at7:40AM Hi,All,firsttimeonthissiteformeandvery,veryuseful. IjustwanttoaddmypositivecommentonthemethodofAnub Philipformyapplication,thisrunsinlessthanasecondcompared to~2:35:00(that's2minutes35sec)forexactlythesameresult usingthepreviousCTEmethod. TheprerankingoftherecordsfortheCTEwasahugebenefit. Theslowermethoddidrunquitefastonasimplerdataset,butsank onthemorecomplextable. Geoff

Subject: Postedby: Postedon: Message:

Subject: Postedby: Postedon: Message:

ihaveaproblem..plssolveit suresh123(viewprofile) Wednesday,August05,2009at7:16AM Actuallyihavetorunthismethodonhugetableofaround65000 rows,andthecolumntobeconcatenatedisntextfield,icannot changetovarcharbecauseofdatalose... wheniusethis"ScalarUDFwithtSQLupdateextension" Mynotesgettruncated... Anyothermethodtodomyjob HowdoIaddnewlinesinsteadofcommas? PeggyScott84(viewprofile) Wednesday,September16,2009at1:46PM Iamtryingtoconcatenaterowvalueswithnewlinesinstead. IneedtodisplaythequeryresultsonaColdFusion8website. ItsoundsbasicbutIhavetriedusingchar(10)char(13) \n,\n\r,\r triedusing<br>,</br> nothingworks. Anyhelp/suggestioniswelcome! Thanks!

Subject: Postedby: Postedon: Message:

Subject: Postedby: Postedon: Message:

CommonLanguageRuntimeErrorInSolution BugMeNot(viewprofile) Thursday,November19,2009at10:35PM Thecodeinthe"UsingCommonLanguageRuntime"sectionofthis articleresultsinthefollowingerror: Usingthegenerictype'System.Collections.Generic.List<T>'requires '1'typearguments Tocorrectthiserror,replaceallreferencesto"List"with "List<string>".

Subject: Postedby: Postedon: Message:

Veryinterestingarticle.. KLynch0803(viewprofile) Monday,February01,2010at3:52PM IlovethisarticleproblemisIdontunderstanditcompletely..I'mfar fromaprogrammerbutI'mtryingtomanipulatesomedataIhaveto insertintoaformimupdatingvaluesin.Cansomeonepleasehelp meeditthisprocesstowrokinMSAccess? IhavethefollowingdatawithmultipleCityandstateValuesthatare equalbutuniquezipcodes.Thislistis43,000rowslong: tbl_City_State CityStateNameZipCode IneedanoutputlikesuchforeachCitystatewithoutduplicatecity statenames... RaleighNC297062970729708 Meaningifthereare3or50RaleighNCinthetableitwillmakeone andaddallthezipcodestotheonecellwiththecitystatename.

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

19/22

04/04/12

Concatenating Row Values in Transact-SQL


IwouldappreciatteanyhelpinadvanceIhavebeentryingtofigure outhowtodothisinexceloraccessforabout2weeksnow.

Subject: Postedby: Postedon: Message:

Veryinterestingarticle.. KLynch0803(viewprofile) Monday,February01,2010at9:35PM IlovethisarticleproblemisIdontunderstanditcompletely..I'mfar fromaprogrammerbutI'mtryingtomanipulatesomedataIhaveto insertintoaformimupdatingvaluesin.Cansomeonepleasehelp meeditthisprocesstowrokinMSAccess? IhavethefollowingdatawithmultipleCityandstateValuesthatare equalbutuniquezipcodes.Thislistis43,000rowslong: tbl_City_State CityStateNameZipCode IneedanoutputlikesuchforeachCitystatewithoutduplicatecity statenames... RaleighNC297062970729708 Meaningifthereare3or50RaleighNCinthetableitwillmakeone andaddallthezipcodestotheonecellwiththecitystatename. IwouldappreciatteanyhelpinadvanceIhavebeentryingtofigure outhowtodothisinexceloraccessforabout2weeksnow.

Subject: Postedby: Postedon: Message: Subject: Postedby: Postedon: Message:

VeryGoodMen. melhorum(viewprofile) Thursday,February11,2010at9:08AM it'scleancode,thanks. Simpler.... dmc(viewprofile) Wednesday,June02,2010at4:59PM Whynotthissolution?? Problem:Toshowallthecitiesascommaseparatedlistforeach region usenorthwind rawdata... selectregion,cityfromcustomerswherelen(region)=2orderby1,2 regioncity AKAnchorage BCTsawassen BCVancouver CASanFrancisco DFCaracas IDBoise MTButte NMAlbuquerque ORElgin OREugene ORPortland ORPortland RJRiodeJaneiro RJRiodeJaneiro RJRiodeJaneiro SPCampinas SPResende SPSaoPaulo SPSaoPaulo SPSaoPaulo SPSaoPaulo WAKirkland WASeattle WAWallaWalla WYLander (25row(s)affected) citieswithineachregion select region, (selectstuff((selectdistinct','+cityas[text()] fromcustomers whereregion=c.region orderby','+city forxmlpath('')),1,1,''))as'cities' fromcustomersc

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

20/22

04/04/12

Concatenating Row Values in Transact-SQL


wherelen(region)=2limitingview groupbyregion regioncities AKAnchorage BCTsawassen,Vancouver CASanFrancisco DFCaracas IDBoise MTButte NMAlbuquerque ORElgin,Eugene,Portland RJRiodeJaneiro SPCampinas,Resende,SaoPaulo WAKirkland,Seattle,WallaWalla WYLander (12row(s)affected) nofunctions,cursors,declares,etc...amImissingsomething??

Subject: Postedby: Postedon: Message:

Re:Whynotthissolution?? Anith(viewprofile) Friday,June25,2010at4:56PM dmc, No,youarenotmissinganything.Itisalreadyaddressedinthe articleunderthesection"TheblackboxXMLmethods". AnithLarson

Subject: Postedby: Postedon: Message:

Greatexamples dmigliore(viewprofile) Thursday,August05,2010at10:09AM Thanksfortheexamplesofthevariousmethods.Thisgivesme morechoicesinhowtosolvetheconcatenationproblem. ConcatusingXQuery originator(viewprofile) Thursday,October28,2010at5:01AM Higuys! I'dliketomentionanotheronefast,XMLbasedand"entity"safe method: declare@iXmlxml SELECT@iXml=( SELECTProductName+',' FROMNorthwind.dbo.Products FORXMLPATH) select@iXml.value('string(/)','nvarchar(max)') Goodluck!

Subject: Postedby: Postedon: Message:

Subject: MigratingfromOracletoSQLServerAggregatefunction Posted kalpesh(viewprofile) by: Posted Monday,February07,2011at12:22AM on: Message:Hi,NeedhelpinconvertingtheStrAgg(ODCIAggregatefromOracle)function (http://download.oracle.com/docs/cd/B14117_01/appdev.101/b10800/dciaggfns.htm#BEJBEBHE) toSQLServercompatible. TherearemanyViewswhichusethisfunctioningenericway.Don'twanttodoitinC#soasto keepinSQLspecific. Select Docid, Protocol, StrAgg(Jan)as'Jan', StrAgg(Feb)as'Feb', StrAgg(Mar)as'Mar', StrAgg(Apr)as'Apr', StrAgg(May)as'May', StrAgg(Jun)as'Jun', StrAgg(Jul)as'Jul', StrAgg(Aug)as'Aug', StrAgg(Sep)as'Sep', StrAgg(Oct)as'Oct', StrAgg(Nov)as'Nov', StrAgg(Dec)as'Dec'

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

21/22

04/04/12

Concatenating Row Values in Transact-SQL


From ( Select Docid, P.Protocol, CaseWhenTo_Char(PL.PamDt,'Mon')='Jan'ThenTo_Char(PL.ActDt,'DDMon')ELSENULL ENDAsJan, CaseWhenTo_Char(PL.PamDt,'Mon')='Feb'ThenTo_Char(PL.ActDt,'DDMon')ELSENULL ENDAsFeb, CaseWhenTo_Char(PL.PamDt,'Mon')='Mar'ThenTo_Char(PL.ActDt,'DDMon')ELSENULL ENDAsMar, ......Dec From ( Select T.DocId, T.Protocol From PAMSTRT, CITYCy WhereCy.CNum<=T.CycleNum )P, PAMSTRDTLPl Where P.DocId=Pl.DocId(+) AndP.CNum=Pl.ActCNum(+) OrderByCNum,PamDt ) GroupbyDocId,Protocol IfIexecutewithoutAggregateIget: DocidProtocolJanFebMar 1P101Jan 1P102Jan02Mar 2P202Mar 2P201Jan05Mar IfIexecutewithAggregateIget: DocidProtocolJanFebMar 1P101Jan,02Jan02Mar 2P201Jan02Mar,05Mar

Anyguidanceappreciatedtogetgenericsolution. Subject: Postedby: Postedon: Message: Peelingback ISAKOS(viewprofile) Wednesday,June08,2011at8:00AM Greatarticle, itsolvedmyissue, Iwouldliketosaythanktoallofyou, regardingtoAnithSen

About|Sitemap|Becomeanauthor|Newsletters |Contactus Privacypolicy |Termsandconditions |20052012RedGateSoftware

www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

22/22

S-ar putea să vă placă și