insert in table with between? - mysql

Im trying to make a table with zip codes and states for Norway and since its in order I want to bulk insert instead of inserting one and one. so from 0000 to 1295 is Oslo so I tried this but is failing anyone have some solution?
insert into poststed (postnr, poststed) values
(between 0000 and 1295, 'Oslo'),
(between 1300 and 1304, 'Sandvika');

I dont know if using this type of between is supported in SQL. but I see a huge duplication in your data model. Better You think about changing it.
Your data model could look like
Start , End , poststed
0000 , 1295 , oslo
This way, you will be done within two rows, and have them indexed, if you want.. and your query can go like
SELECT poststed FROM MYTABLE WHERE :value between MYTABLE.START AND MYTABLE.END
Something similar to this should work. Please refer to this question for more query details - Select BETWEEN column values
Hope this helps!

Why not use a for loop? You havent specified which version of SQL you are using, let me know and I will find the right syntax, but here is roughly what you need
https://www.techonthenet.com/sql_server/loops/for_loop.php

Generate automatic data without between:
-- step 1
declare #start int = 0
declare #end int = 1295
;with numcte
AS
(
SELECT #start [SEQUENCE]
UNION all
SELECT [SEQUENCE] + 1
FROM
numcte WHERE [SEQUENCE] < #end
)
INSERT into poststed (postnr, poststed)
SELECT *,'Oslo' FROM numcte option (maxrecursion 0)
--step 2
declare #start2 int = 1300
declare #end2 int =1304
;with numcte
AS
(
SELECT #start2 [SEQUENCE]
UNION all
SELECT [SEQUENCE] + 1
FROM
numcte WHERE [SEQUENCE] < #end2
)
INSERT into poststed (postnr, poststed)
SELECT *,'Sandvika' FROM numcte option (maxrecursion 0)

Related

Mysql: replace leading zeroes inside text

I wish to replace cca 3 500 000 values in Mysql Table. Each value is string in the form of AB00123012 and I wish to remove leading zeroes after letters - i.e. get AB123012 (zeroes inside number should be kept).
The value has always exactly 10 characters.
Since Mysql does not allow replace by regex, I have used following function:
DELIMITER $$
CREATE FUNCTION fn_RawRingNumber (rn CHAR(10))
RETURNS CHAR(10) DETERMINISTIC
BEGIN
DECLARE newrn CHAR(10);
DECLARE pos INT(8);
DECLARE letters CHAR(2);
DECLARE nr CHAR(8);
IF (CHAR_LENGTH(rn) = 10) THEN
SET pos = (SELECT POSITION('0' IN rn));
SET letters = (SELECT SUBSTRING_INDEX(rn, '0', 1));
SET nr = (SELECT TRIM(LEADING '0' FROM SUBSTRING(rn,pos)));
SET newrn = (SELECT CONCAT(letters, nr));
ELSE
SET newrn = rn;
END IF;
RETURN newrn;
END$$
DELIMITER ;
While this works, it is rather slow and I am wondering, if there is not a better way to do this?
If you can afford to take your site offline for a few minutes, the fastest way would be to dump, process and re import. Since the current operation makes queries/inserts on that table pretty slow, so you are probably better off with a dump/process/import anyway.
Step 1 dump.
SELECT INTO OUTFILE is your friend here
Step 2 process
Use your favourite programming language or if you are lucky to be on linux, something like sed or even cut. If you need help with the regex post a comment.
Step 3 reimport
After clearing out the table. Do a LOAD DATA INFILE.
these three steps should all be reasonably quick. Specially if you have a n index on that column.
Try this
Note: I not tested this with many rows and don't know how this is efficient.
Also, if this is fast, please before using this, think all possible variations, which may occurs with your string, may be I missed some variants, not sure 100%.
select case
when INSTR(col, '0') = 2 then concat( substr(col, 1, 1), substr(col, 2) * 1)
when INSTR(col, '0') = 3 and substr(col, 2, 1) not in('1','2','3','4','5','6','7','8','9') then concat( substr(col, 1, 2), substr(col, 3) * 1)
else col
end
from (
select 'AB00123012' as col union all
select 'A010000123' as col union all
select 'A1000000124' as col union all
select 'A0000000124' as col union all
select '.E00086425' as col
) t

SQL Server T-SQL breaking a string into a temp table for a join

We have a SQL Server Scalar Function and part of the process is to take one of the input values and do the following
'inputvalue'
Create a table variable and populate with the following rows
inputvalue
inputvalu
inputval
inputva
inputv
input
inpu
inp
Then this table is joined to a query, ordered by len of the inputvalue desc and returns the top 1. The actual code is here
DECLARE #Result NVARCHAR(20);
DECLARE #tempDialCodes TABLE (tempDialCode NVARCHAR(20));
DECLARE #counter INT = LEN(#PhoneNumber);
WHILE #counter > 2
BEGIN
INSERT INTO #tempDialCodes(tempDialCode) VALUES(#PhoneNumber);
SET #PhoneNumber = SUBSTRING(#PhoneNumber, 1, #counter - 1);
SET #counter = #counter - 1;
END
SET #Result = (SELECT TOP 1 [DialCodeID]
FROM DialCodes dc JOIN #tempDialCodes s
ON dc.DialCode = s.tempDialCode
ORDER BY LEN(DialCode) DESC);
RETURN #Result
It works fine but I am asking if there is a way to replace the while loop and somehow joining to the inputvalue to get the same result. When I say it works fine, it's too dam slow but it does work.
I'm stumped on how to break up this string without using a loop and to a table variable but my warning light tells me this is not efficient for running against a table with a million rows.
Are you familiar with tally tables? The speed difference can be incredible. I try to replace every loop with a tally table if possible. The only time I haven't been able to so far is when calling a proc from within a cursor. If using this solution I would recommend a permanent dbo.Tally table with a sufficiently large size rather than recreating every time in the function. You will find other uses for it!
declare #PhoneNumber nvarchar(20) = 'inputvalue';
declare #tempDialCodes table (tempDialCode nvarchar(20));
--create and populate tally table if you don't already a permanent one
--arbitrary 1000 rows for demo...you should figure out if that is enough
--this a 1-based tally table - you will need to tweak if you make it 0-based
declare #Tally table (N int primary key);
insert #Tally
select top (1000) row_number() over (order by o1.object_id) from sys.columns o1, sys.columns o2 order by 1;
--select * from #Tally order by N;
insert #tempDialCodes
select substring(#PhoneNumber, 1, t.N)
from #Tally t
where t.N between 3 and len(#PhoneNumber)
order by t.N desc;
select *
from #tempDialCodes
order by len(tempDialCode) desc;

How to split string in sql server and put it in a table

My input is like
(abcd#123, xyz#324, def#567)
I want an output
col1 Col2
abcd 123
xyz 324
def 567
and so on
Column 1 should have abcd and xyz, and column 2 should have 123 and 324 both in different rows and so on. and the String can be of any size.
Thank you
Try this
SELECT LEFT('abcd#123', CHARINDEX('#', 'abcd#123')-1),
RIGHT('abcd#123', CHARINDEX('#', 'abcd#123')-1)
You will need to use CHARINDEX() and SUBSTRING() functions to split your input values.
your actual problem is turning a complex String into a table i gues.
That for i found help with a procedure about 1 year ago, that does exactly that:
CREATE FUNCTION [dbo].[fnSplitString] (
#myString varchar(500),
#deliminator varchar(10))
RETURNS
#ReturnTable TABLE (
[id] [int] IDENTITY(1,1) NOT NULL,
[part] [varchar](50) NULL
)
AS
BEGIN
Declare #iSpaces int
Declare #part varchar(50)
Select #iSpaces = charindex(#deliminator,#myString,0)
While #iSpaces > 0
BEGIN
Select #part = substring(#myString,0,charindex(#deliminator,#myString,0))
Insert Into #ReturnTable(part)
Select #part
Select #myString = substring(#mystring,charindex(#deliminator,#myString,0)+ len(#deliminator),len(#myString) - charindex(' ',#myString,0))
Select #iSpaces = charindex(#deliminator,#myString,0)
END
If len(#myString) > 0
Insert Into #ReturnTable
Select #myString
RETURN
END
Create this procedure and you can do:
DECLARE #TestString varchar(50)
SET #TestString = 'abcd#123,xyz#324,def#567'
Select * from dbo.fnSplitString(#TestString, ',')
Result:
id| part
1 | abcd#123
2 | xyz#324
3 | def#567
this part you can combine with Leonardos answer:
SELECT
LEFT(part, CHARINDEX('#', part)-1) As Col1,
RIGHT(part, LEN(part) - CHARINDEX('#', part)) As Col2
from dbo.fnSplitString(#TestString, ',')
to get your problem solved.
(little note: the function has little issues with whitespaces, so please try to avoid them there)

splitting a row in sql with different information in sql server [duplicate]

How to split a string in SQL Server.
Example:
Input string: stack over flow
Result:
stack
over
flow
if you can't use table value parameters, see: "Arrays and Lists in SQL Server 2008 Using Table-Valued Parameters" by Erland Sommarskog , then there are many ways to split string in SQL Server. This article covers the PROs and CONs of just about every method:
"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog
You need to create a split function. This is how a split function can be used:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(#Parameter) s ON y.ID=s.Value
I prefer the number table approach to split a string in TSQL but there are numerous ways to split strings in SQL Server, see the previous link, which explains the PROs and CONs of each.
For the Numbers Table method to work, you need to do this one time table setup, which will create a table Numbers that contains rows from 1 to 10,000:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
Once the Numbers table is set up, create this split function:
CREATE FUNCTION [dbo].[FN_ListToTable]
(
#SplitOn char(1) --REQUIRED, the character to split the #List string on
,#List varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN
(
----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
SELECT
ListValue
FROM (SELECT
LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(#SplitOn, List2, number+1)-number - 1))) AS ListValue
FROM (
SELECT #SplitOn + #List + #SplitOn AS List2
) AS dt
INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
WHERE SUBSTRING(List2, number, 1) = #SplitOn
) dt2
WHERE ListValue IS NOT NULL AND ListValue!=''
);
GO
You can now easily split a CSV string into a table and join on it:
select * from dbo.FN_ListToTable(' ','stack over flow')
OUTPUT:
ListValue
-------------------
stack
over
flow
(3 row(s) affected)
A common set-based solution to this kind of problem is to use a numbers table.
The following solution uses a simple recursive CTE to generate the numbers table on the fly - if you need to work with longer strings, this should be replaced with a static numbers table.
DECLARE #vch_string varchar(max)
DECLARE #chr_delim char(1)
SET #chr_delim = ' '
SET #vch_string = 'stack over flow'
;WITH nums_cte
AS
(
SELECT 1 AS n
UNION ALL
SELECT n+1 FROM nums_cte
WHERE n < len(#vch_string)
)
SELECT n - LEN(REPLACE(LEFT(s,n),#chr_delim,'')) + 1 AS pos
,SUBSTRING(s,n,CHARINDEX(#chr_delim, s + #chr_delim,n) -n) as ELEMENT
FROM (SELECT #vch_string as s) AS D
JOIN nums_cte
ON n <= LEN(s)
AND SUBSTRING(#chr_delim + s,n,1) = #chr_delim
OPTION (MAXRECURSION 0);
I know this question was for SQL Server 2008 but things evolve so starting with SQL Server 2016 you can do this
DECLARE #string varchar(100) = 'Richard, Mike, Mark'
SELECT value FROM string_split(#string, ',')
CREATE FUNCTION [dbo].[Split]
(
#List varchar(max),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Value nvarchar(max)
)
AS
BEGIN
While (Charindex(#SplitOn,#List)>0)
Begin
Insert Into #RtnValue (value)
Select
Value = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
Set #List = Substring(#List,Charindex(#SplitOn,#List)+len(#SplitOn),len(#List))
End
Insert Into #RtnValue (Value)
Select Value = ltrim(rtrim(#List))
Return
END
Create Above Function And Execute Belowe Query To Get Your Result.
Select * From Dbo.Split('Stack Over Flow',' ')
Suggestion : use delimiter for get split value. it's better. (for ex. 'Stack,Over,Flow')
Hard. Really hard - Strin Manipulation and SQL... BAD combination. C# / .NET for a stored procedure is a way, could return a table defined type (table) with one item per row.

SQL Server: Split operation

How to split a string in SQL Server.
Example:
Input string: stack over flow
Result:
stack
over
flow
if you can't use table value parameters, see: "Arrays and Lists in SQL Server 2008 Using Table-Valued Parameters" by Erland Sommarskog , then there are many ways to split string in SQL Server. This article covers the PROs and CONs of just about every method:
"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog
You need to create a split function. This is how a split function can be used:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(#Parameter) s ON y.ID=s.Value
I prefer the number table approach to split a string in TSQL but there are numerous ways to split strings in SQL Server, see the previous link, which explains the PROs and CONs of each.
For the Numbers Table method to work, you need to do this one time table setup, which will create a table Numbers that contains rows from 1 to 10,000:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
Once the Numbers table is set up, create this split function:
CREATE FUNCTION [dbo].[FN_ListToTable]
(
#SplitOn char(1) --REQUIRED, the character to split the #List string on
,#List varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN
(
----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
SELECT
ListValue
FROM (SELECT
LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(#SplitOn, List2, number+1)-number - 1))) AS ListValue
FROM (
SELECT #SplitOn + #List + #SplitOn AS List2
) AS dt
INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
WHERE SUBSTRING(List2, number, 1) = #SplitOn
) dt2
WHERE ListValue IS NOT NULL AND ListValue!=''
);
GO
You can now easily split a CSV string into a table and join on it:
select * from dbo.FN_ListToTable(' ','stack over flow')
OUTPUT:
ListValue
-------------------
stack
over
flow
(3 row(s) affected)
A common set-based solution to this kind of problem is to use a numbers table.
The following solution uses a simple recursive CTE to generate the numbers table on the fly - if you need to work with longer strings, this should be replaced with a static numbers table.
DECLARE #vch_string varchar(max)
DECLARE #chr_delim char(1)
SET #chr_delim = ' '
SET #vch_string = 'stack over flow'
;WITH nums_cte
AS
(
SELECT 1 AS n
UNION ALL
SELECT n+1 FROM nums_cte
WHERE n < len(#vch_string)
)
SELECT n - LEN(REPLACE(LEFT(s,n),#chr_delim,'')) + 1 AS pos
,SUBSTRING(s,n,CHARINDEX(#chr_delim, s + #chr_delim,n) -n) as ELEMENT
FROM (SELECT #vch_string as s) AS D
JOIN nums_cte
ON n <= LEN(s)
AND SUBSTRING(#chr_delim + s,n,1) = #chr_delim
OPTION (MAXRECURSION 0);
I know this question was for SQL Server 2008 but things evolve so starting with SQL Server 2016 you can do this
DECLARE #string varchar(100) = 'Richard, Mike, Mark'
SELECT value FROM string_split(#string, ',')
CREATE FUNCTION [dbo].[Split]
(
#List varchar(max),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Value nvarchar(max)
)
AS
BEGIN
While (Charindex(#SplitOn,#List)>0)
Begin
Insert Into #RtnValue (value)
Select
Value = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
Set #List = Substring(#List,Charindex(#SplitOn,#List)+len(#SplitOn),len(#List))
End
Insert Into #RtnValue (Value)
Select Value = ltrim(rtrim(#List))
Return
END
Create Above Function And Execute Belowe Query To Get Your Result.
Select * From Dbo.Split('Stack Over Flow',' ')
Suggestion : use delimiter for get split value. it's better. (for ex. 'Stack,Over,Flow')
Hard. Really hard - Strin Manipulation and SQL... BAD combination. C# / .NET for a stored procedure is a way, could return a table defined type (table) with one item per row.