{"id":864,"date":"2011-09-09T20:15:13","date_gmt":"2011-09-10T01:15:13","guid":{"rendered":"http:\/\/anvil-of-time.com\/wordpress\/?p=864"},"modified":"2021-03-10T20:51:28","modified_gmt":"2021-03-11T01:51:28","slug":"splitting-up-a-string-or-text-in-sql","status":"publish","type":"post","link":"https:\/\/anvil-of-time.com\/powerbuilder\/splitting-up-a-string-or-text-in-sql\/","title":{"rendered":"Splitting up a String or Text in SQL"},"content":{"rendered":"<p>Here is a way to split up a block of text and return a result set based on a delimeter. A table function is used to do the &#8216;heavy lifting&#8217; and, utilizing some newer features of SQL Server (2005 and 2008), you can even join to it providing for even greater flexability.<\/p>\n<p>This situation I was facing involved the display of text within a PowerBuilder Datawindow. When the data for a specific report datawindow was retrieved the display was sometimes cut off or overlapped other portions of the report layout (the header usually). This only seemed to happen when the text column was included on the report and the data within the column exceeded the number of lines you would expect to print on a single page. Since the text data was originally input by users, it almost always included carriage return \/ linefeed (CRLF) line terminators within it. The easiest way to correct this was to change the data source of the datawindow to parse the text and split it up based on these CRLF sequences. This way I would get a result set of many lines, each with a portion of the text, rather than one with the entire text block (which was what PowerBuilder was having trouble sizing\/positioning correctly).<\/p>\n<p>The table function was inspired by the example found<a href=\"http:\/\/www.simple-talk.com\/sql\/learn-sql-server\/robyn-pages-sql-server-string-manipulation-workbench\/\" target=\"_blank\" rel=\"noopener\"> here<\/a>.<\/p>\n<pre name=\"code\" class=\"sql\">CREATE FUNCTION [dbo].[uft_splitnotes] (@StringArray NVARCHAR(MAX),\n                                        @Delimiter   NVARCHAR(30))\nRETURNS @Results TABLE \n(\n  SeqNo INT IDENTITY(1, 1),\n  Item  NVARCHAR(MAX)\n)\nAS\n  BEGIN\n      DECLARE @Next INT\n      DECLARE @lenStringArray INT\n      DECLARE @lenDelimiter INT\n      DECLARE @ii INT\n\n      --initialise everything\n      IF UPPER(@Delimiter) = &#039;SPACE&#039;\n        BEGIN\n            SET @Delimiter = &#039; &#039;\n        END\n      IF UPPER(@Delimiter) = &#039;[CR]&#039;\n        BEGIN\n            SET @Delimiter = CHAR(13)\n        END\n      IF UPPER(@Delimiter) = &#039;[LF]&#039;\n        BEGIN\n            SET @Delimiter = CHAR(10)\n        END\n      IF UPPER(@Delimiter) = &#039;[CRLF]&#039;\n        BEGIN\n            SET @Delimiter = CHAR(13) + CHAR(10)\n        END\n      IF UPPER(@Delimiter) = &#039;CHAR(13)&#039;\n        BEGIN\n            SET @Delimiter = CHAR(13)\n        END\n      IF UPPER(@Delimiter) = &#039;CHAR(10)&#039;\n        BEGIN\n            SET @Delimiter = CHAR(10)\n        END\n      IF @Delimiter = &#039;CHAR(13) + CHAR(10)&#039;\n        BEGIN\n            SET @Delimiter = CHAR(13) + CHAR(10)\n        END\n\n      SELECT @ii = 1,\n             @lenStringArray = LEN(REPLACE(@StringArray, &#039; &#039;, &#039;|&#039;)),\n             @lenDelimiter = LEN(REPLACE(@Delimiter, &#039; &#039;, &#039;|&#039;))\n      --notice we have to be cautious about LEN with trailing spaces!\n      --while there is more of the string\u2026\n      WHILE @ii &lt;= @lenStringArray\n        BEGIN--find the next occurrence of the delimiter in the stringarray\n            SELECT @Next = CHARINDEX(@Delimiter, @StringArray + @Delimiter, @ii)\n\n            INSERT INTO @Results\n                        (Item)\n            SELECT SUBSTRING(@StringArray, @ii, @Next - @ii)\n            --note that we can get all the items from the list by appeending a\n            --delimiter to the final string\n            SELECT @ii = @Next + @lenDelimiter\n        END\n      RETURN\n  END<\/pre>\n<p>Now since I wanted to split the string based on embedded CRLF sequences, I set up a series of IF statements to allow for various ways to designate these. I&#8217;m sure there are better ways to do this part.<\/p>\n<p>Sample output:<br \/>\n<a href=\"http:\/\/anvil-of-time.com\/wordpress\/wp-content\/uploads\/2011\/09\/notessplit.png\"><img loading=\"lazy\" class=\"aligncenter wp-image-866 size-full\" title=\"notessplit\" src=\"https:\/\/anvil-of-time.com\/wp-content\/uploads\/2011\/09\/notessplit.png\" alt=\"\" width=\"440\" height=\"231\" srcset=\"https:\/\/anvil-of-time.com\/wp-content\/uploads\/2011\/09\/notessplit.png 440w, https:\/\/anvil-of-time.com\/wp-content\/uploads\/2011\/09\/notessplit-300x157.png 300w, https:\/\/anvil-of-time.com\/wp-content\/uploads\/2011\/09\/notessplit-150x78.png 150w\" sizes=\"(max-width: 440px) 100vw, 440px\" \/><\/a><\/p>\n<p>Although this was written in SQL Server 2008, I&#8217;m sure it can be replicated in other flavors of SQL.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here is a way to split up a block of text and return a result set based on a delimeter. A table function is used to do the &#8216;heavy lifting&#8217; and, utilizing some newer features of SQL Server (2005 and 2008), you can even join to it providing for even greater flexability. This situation I&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[8,3,10],"tags":[12,16,15],"_links":{"self":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/864"}],"collection":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/comments?post=864"}],"version-history":[{"count":8,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/864\/revisions"}],"predecessor-version":[{"id":1977,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/864\/revisions\/1977"}],"wp:attachment":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/media?parent=864"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/categories?post=864"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/tags?post=864"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}