Related to string manipulation - sql

I have a table of crop which contain a column with crop name For Example Fruit and Nuts, Vegetables and Melons. I have to use T-SQL and remove the 'and' insert the spaces with a underscore and a text crop.groups should be added in front. For example Fruit and Nuts will become crop.groups.fruit_nuts. I have to to do these for all the crops together in SQL. When we run the query a separate column with these transformation should be generated. Also I have to create a function doing all this to me.
My Function:
CREATE function dbo.translationkey_v10
(
#column_name nchar(15)
)
returns nvarchar(1000)
as
begin
DECLARE #numletters int;
DECLARE #counter int;
DECLARE #str nvarchar(6);
DECLARE #newcolumn_name nvarchar(50)
SET #numletters = LEN(#column_name);
SET #counter = 1;
SET #newcolumn_name = '';
WHILE #counter <= #numletters
BEGIN
-- a. read next character:
----------------------------------------------------------------
SET #str = LOWER(SUBSTRING(#column_name, #counter, 1));
-- b. search for and in the string 'and':
----------------------------------------------------------------
IF (#str LIKE '%and%')
BEGIN
SET #str = REPLACE(#str,' and','')
END
-- c. check for space:
----------------------------------------------------------------
IF UNICODE(#str) = 32
BEGIN
SET #str = '_';
END
SET #newcolumn_name = #newcolumn_name + #str;
SET #counter = #counter + 1;
END
RETURN CONCAT('crop.groups.',#newcolumn_name)
END
Sample data
Crop name : Beverages and spice crops
Translation output : crop.group.beverages_spice_crops

This would seem very simple using replace:
select cropname, Concat('crop.groups.', Replace(cropname, ' and ','_'))
from crop

Related

Using a SQL User Defined Function with an UPDATE

I have a Function that removes any non alpha numerical characters, and a stored procedure that does several updates to the EMIR table. My question is, how do I write an update statement to call the function RemoveNonAlphaNumericCharacters and update the field 'Underlying_Security_Name'
USE EMIR
GO
ALTER FUNCTION [dbo].[RemoveNonAlphaNumericCharacters]
(
-- Add the parameters for the function here
#String NVARCHAR(100)
)
RETURNS nvarchar(100)
AS
BEGIN
DECLARE #Keep_Value AS NVARCHAR(50)
SET #Keep_Value = '%[^a-z0-9 ]%'
WHILE PATINDEX(#Keep_Value, #String) > 0
BEGIN
SET #String = STUFF(#String, PATINDEX(#Keep_Value, #String), 1, '')
END
RETURN #String
END
GO
You could do something like this.
UPDATE EMIR.table_name
SET Underlying_Security_Name = dbo.RemoveNonAlphaNumericCharacters(Underlying_Security_Name​);

Find all ERDs containing table with specified name

Is it possible that I can query for names of all ERDs (Entity Relationship Diagram) which contain table with name
Like '%mytable%'
Something like this:
select *
from <ERD objects>
where tableName like '%%'
Actually, I have a large Database with lots of ERDs. So, to understand the scope of a table I want to browse ERDs of that specific table.
As I understand you need a list of tables contained in a database diagrams. There you can help this article. I will add part of it here:
The diagram itself is stored in a binary field. And you can not convert it into readable form without difficulties. For deserializing this field (called definition) we need 2 functions:
CREATE FUNCTION [dbo].[Tool_VarbinaryToVarchar_Text]
(
#VarbinaryValue VARBINARY(max),
#bitASCIIOnly BIT = 0
)
RETURNS VARCHAR(max) AS
BEGIN
DECLARE #NumberOfBytes INT
SET #NumberOfBytes = DATALENGTH(#VarbinaryValue)
-- PART ONE --
IF (#NumberOfBytes > 4)
BEGIN
DECLARE #FirstHalfNumberOfBytes INT
DECLARE #SecondHalfNumberOfBytes INT
SET #FirstHalfNumberOfBytes = #NumberOfBytes/2
SET #SecondHalfNumberOfBytes = #NumberOfBytes - #FirstHalfNumberOfBytes
-- Call this function recursively with the two parts of the input split in half
RETURN dbo.Tool_VarbinaryToVarchar_Text(CAST(SUBSTRING(#VarbinaryValue, 1 , #FirstHalfNumberOfBytes) AS VARBINARY(max)),#bitASCIIOnly)
+ dbo.Tool_VarbinaryToVarchar_Text(CAST(SUBSTRING(#VarbinaryValue, #FirstHalfNumberOfBytes+1 , #SecondHalfNumberOfBytes) AS VARBINARY(max)),#bitASCIIOnly)
END
IF (#NumberOfBytes = 0)
BEGIN
RETURN '' -- No bytes found, therefore no 'hex string' is returned
END
-- PART TWO --
DECLARE #HighByte INT
-- #NumberOfBytes <= 4 (four or less characters/8 hex digits were input)
-- eg. 88887777 66665555 44443333 22221111
-- We'll process ONLY the right-most (least-significant) Byte, which consists
-- of eight bits
-- 2. Carve off the rightmost eight bits/single hex digit (ie 22221111)
-- Divide by 16 does a shift-left (now processing 2222)
SET #HighByte = CAST(#VarbinaryValue AS INT) & 255
IF #bitASCIIOnly = 1 AND (#HighByte < 32 OR #HighByte > 126) SET #HighByte=13;
-- 3. Trim the byte (two hex values) from the right (least significant) input Binary
-- in preparation for further parsing
SET #VarbinaryValue = SUBSTRING(#VarbinaryValue, 1, (#NumberOfBytes-1))
-- 4. Recursively call this method on the remaining Binary data, concatenating the text
-- 'value' we just decoded as their ASCII character representation
-- ie. we pass 88887777 66665555 44443333 back to this function, adding X to the result string
RETURN dbo.Tool_VarbinaryToVarchar_Text(#VarbinaryValue,#bitASCIIOnly) +
CHAR(#HighByte)
END
And:
CREATE FUNCTION [dbo].[fnTool_ScriptDiagram2005_Text]()
RETURNS
#tblOut TABLE
(
-- Add the column definitions for the TABLE variable here
diagramname NVARCHAR(128),
diagram_id INT PRIMARY KEY,
diagram_text VARCHAR(MAX),
diagram_ASCII VARCHAR(MAX)
)
AS
BEGIN
DECLARE #name NVARCHAR(128);
DECLARE #diagram_id INT;
DECLARE #index INT;
DECLARE #size INT;
DECLARE #chunk INT;
DECLARE #line VARCHAR(MAX);
DECLARE #lineASC VARCHAR(MAX);
DECLARE #CurrentPos INT;
SELECT #CurrentPos = MIN(diagram_id) FROM dbo.sysdiagrams;
WHILE (#CurrentPos IS NOT NULL)
BEGIN
-- Set start index, and chunk 'constant' value
SET #index = 1; --
SET #chunk = 32; -- values that work: 2, 6
-- values that fail: 15,16, 64
SELECT #diagram_id = diagram_id,
#size = DATALENGTH(definition),
#name = name
FROM dbo.sysdiagrams
WHERE diagram_id = #CurrentPos;
-- Now with the diagram_id, do all the work
SET #line = '';
SET #lineASC = '';
WHILE #index < #size
BEGIN
-- Output as many UPDATE statements as required to append all the diagram binary
-- data, represented as hexadecimal strings
SELECT #line = #line + dbo.Tool_VarbinaryToVarchar_Text(SUBSTRING (definition, #index, #chunk),0),
#lineASC = #lineASC + dbo.Tool_VarbinaryToVarchar_Text(SUBSTRING (definition, #index, #chunk),1)
FROM dbo.sysdiagrams
WHERE diagram_id = #CurrentPos;
SET #index = #index + #chunk;
END
INSERT INTO #tblOut (diagramname, diagram_id, diagram_text, diagram_ASCII)
VALUES (#name, #diagram_id, #line, REPLACE(#lineASC,CHAR(13),''));
SELECT #CurrentPos = MIN(diagram_id)
FROM dbo.sysdiagrams
WHERE diagram_id > #CurrentPos;
END
RETURN;
END
After that you can run:
SELECT *
FROM [dbo].[fnTool_ScriptDiagram2005_Text] ()
WHERE diagram_ASCII LIKE '%TableToFind%'
For example I have created diagram TestDiagram with 2 tables named whatever and IE_Stat. In return query:
Root EntrypfoBCompObj_ !"#$%&'()*+,-.123456789:(}5n]4o[\0V?[?i???V?[?i??T,,,4") -bH''Uu94941#xV4XdboIE_StatMicrosoft DDS Form 2.0Embedded Object9q&sch_labels_visibled(ActiveTableViewMode1 TableViewMode:0:4,0,28DdsStreamSchema UDV Default&/DSREF-SCHEMA-CONTENTS,0Schema UDV Default Post V66;4,0,2310,1,1890,5,1260 TableViewMode:12,0,284,0,2805 TableViewMode:22,0,284,0,2310 TableViewMode:32,0,284,0,2310 TableViewMode:4>4,0,284,0,2310,12,2730,11,1680(ActiveTableViewMode1 TableViewMode:0:4,0,284,0,2310,1,1890,5,1260 TableViewMode:12,0,284,0,2805 TableViewMode:22,0,284,0,2310 TableViewMode:32,0,284,0,2310 TableViewMode:4>4,0,284,0,2310,12,2730,11,1680NaQW9 LHEData Source=********;Initial Catalog=test;Integrated Security=True;MultipleActiveResultSets=False;TrustServerCertificate=True;Packet Size=4096;Application Name="Microsoft SQL Server Management Studio"TestDiagram&whateverdbo$IE_StatdbokE7d2pN{1634CDD7-0888-42E3-9FA2-B6D32563B91D}bR
you can see both table names.

Compare if textfield value is greater then x

How can I compare a numeric value in a textfield against any given value x?
Iam writing the code in TSQL.
See code below:
DECLARE #TA_SM varchar(5000)
DECLARE #TA_MSD varchar(5000)
DECLARE #T_SUM int(5)
SET #TA_SM = '[field name='Toelichting_advies_ISM']'
SET #TA_MSD = '[field name='Toelichting_advies_MSD']'
SET #T_SUM = '[field name='Offerte_totaalsom']'
IF ((#TA_SM = '') OR (#TA_MSD = '')) AND (#T_SUM >25.000)
SELECT 1
ELSE
SELECT 2
I get a error message saying:
Must declare the table value #T_SUM
The statement before the AND operator is working just fine.
Change the DECLARE #T_SUM int(5) to DECLARE #T_SUM int.
If you only want to have 5 digits use NUMERIC instead of INT.
EDIT 1 - Full code.
This should run through in TSQL without error but I am not sure if this is the result you are looking for. I have added extra quote marks to your variables definitions.
BEGIN
DECLARE #TA_SM varchar(5000)
DECLARE #TA_MSD varchar(5000)
DECLARE #T_SUM int
SET #TA_SM = '[field name=''Toelichting_advies_ISM'']'
SET #TA_MSD = '[field name=''Toelichting_advies_MSD'']'
SET #T_SUM = '[field name=''Offerte_totaalsom'']'
IF ((#TA_SM = '') OR (#TA_MSD = '')) AND (#T_SUM >25.000)
SELECT 1
ELSE
SELECT 2
END

To creating a dynamic union query in sql server

I am trying to loop through my counter to create a dynamic sql query which should finally look like
I am trying to use this approach to get the final query but doesnt
seems to work
declare #CurrentRow int
set #CurrentRow =0;
declare #RowsToProcess int
declare #FinalHistoricalQuery varchar(5000)
WHILE #CurrentRow<3
BEGIN
SET #FinalHistoricalQuery =' select 11'+convert(varchar(20),#CurrentRow) + ' union '
SET #CurrentRow=#CurrentRow+1
END
SET #FinalHistoricalQuery = left(#FinalHistoricalQuery,len(#FinalHistoricalQuery)-6)
exec (#FinalHistoricalQuery)
the final ouput that i am looking for is 110 111 112 but it comes as 112
Any suggestion would be helpfull
You missed to use the counter in dynamic query. Try something like this.
WHILE #CurrentRow<#RowsToProcess
BEGIN
SET #FinalHistoricalQuery +=' select id from table'+convert(varchar(20),#CurrentRow) + ' union '
SET #CurrentRow=#CurrentRow+1
END
SET #FinalHistoricalQuery = left(#FinalHistoricalQuery,len(#FinalHistoricalQuery)-6)
exec (#FinalHistoricalQuery)

declaring T-Sql parameter for comma delimited list of integers

I have a table that contains a list of performances. These performances are grouped by production number. What I am trying to do is create a stored procedure that will return the last performance for each production entered. I would like to be able to input the production ids as a list of ids. Below is my procedure so far. Difficulty is I'm not sure how best to declare the #prod_no parameter to be used in the IN statement.
CREATE PROCEDURE IP_MAX_PERF_DATE
-- Add the parameters for the stored procedure here
#prod_no
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT [prod_season_no], MAX([perf_dt]) As max_dt FROM [T_PERF] WHERE [prod_season_no] IN (#prod)
GROUP By [prod_season_no];
END
GO
Any ideas
Try the sp_executesql
CREATE PROCEDURE IP_MAX_PERF_DATE
#prod_no nvarchar(500)
AS
BEGIN
SET NOCOUNT ON;
declare #statement nvarchar(1000)
set #statement = N'SELECT [prod_season_no], MAX([perf_dt]) As max_dt FROM [T_PERF] WHERE [prod_season_no] IN (' + #prod_no + ') GROUP By [prod_season_no]'
EXEC sp_executesql
#stmt = #statement
END
GO
generally there are three ways to pass in a list of Ids:
Option 1: use comma separated list and split it in the stored procedure. this requires you to have a split function, or use dynamic sql (not preferred most of the time due to performance problem - at least hard to see the execution plan and you lose the point of using stored procedure to optimize your query)
Option 2: use xml, and again, you need to query the xml to find out the Ids
Option 3: use table valued parameter, this requires you to have a user defined table type
a detailed comparison could be found here:
http://www.adathedev.co.uk/2010/02/sql-server-2008-table-valued-parameters.html
This is what I've always done for passing in comma sepearted Integer IDs.
ALTER FUNCTION [dbo].[SplitArray]
(
#List varchar(500)
)
RETURNS
#ArrayValues table
(
ListID int
)
AS
BEGIN
DECLARE #ListID varchar(10), #Pos int
SET #List = LTRIM(RTRIM(#List))+ ','
SET #Pos = CHARINDEX(',', #List, 1)
IF REPLACE(#List, ',', '') <> ''
BEGIN
WHILE #Pos > 0
BEGIN
SET #ListID = LTRIM(RTRIM(LEFT(#List, #Pos - 1)))
IF #ListID <> ''
BEGIN
INSERT INTO #ArrayValues (ListID)
VALUES (CAST(#ListID AS int)) --Use Appropriate conversion
END
SET #List = RIGHT(#List, LEN(#List) - #Pos)
SET #Pos = CHARINDEX(',', #List, 1)
END
END
RETURN
END
To use it, simply join it on your query like so:
Select a.* From Apples a Inner Join dbo.SplitArray(#IDList) array on a.AppleID = array.ListID