SQL Server sequence set current value - sql-server

I am using SQL Server 2012 (v11.0.2100) and I want to create a sequence that starts with a random (dynamic) number but I wasn't able to do this, also I put my effort to find a good solution for this but I haven't found something that will satisfy me.
The case that I tried and failed:
DECLARE #sth bigint
SET #sth = 1000
ALTER SEQUENCE StreamEntrySequence
RESTART WITH #sth;
Error :
Incorrect syntax near '#sth'
An ugly solution
declare #sth bigint;
declare #i bigint;
SET #sth = 100000 ;
while #i<#sth;
BEGIN
SET #i= next value for StreamEntrySequence;
END
Is there other way to set the current value or the start value to a random value? Maybe using server procedures?

As has been mentioned, this would require dynamic SQL since alter sequence requires a constant for the restart argument.
You might do something like this, then:
DECLARE #sth bigint;
SET #sth = 1000;
DECLARE #sql nvarchar(max);
SET #sql = N'ALTER SEQUENCE StreamEntrySequence RESTART WITH ' + cast(#sth as nvarchar(20)) + ';';
EXEC SP_EXECUTESQL #sql;

Try
ALTER SEQUENCE foo.fee
RESTART
Or:
ALTER SEQUENCE foo.fee
RESTART WITH 1
http://msdn.microsoft.com/en-us/library/ff878572.aspx

Just use
SELECT setval('seq',0,false);
It sets the value of the sequence "seq" to 0.

Related

XPath abs function not working while using in SQL Server

We have a stored procedure
CREATE PROCEDURE [dbo].[usp_s_eval_expr]
#formula NVARCHAR(max),
#result SQL_VARIANT OUTPUT
AS
BEGIN
DECLARE #sql NVARCHAR(max)
DECLARE #cal_value FLOAT
SET #sql = N'DECLARE #x xml=''''SELECT #cal_value=CAST(#x.query('''+#formula+''') as nvarchar(max))'
EXEC sp_executesql #sql,N'#cal_value FLOAT OUTPUT',#cal_value OUTPUT
SET #result = #cal_value
SELECT #result
END
GO
It is created to evaluate mathematical expressions, I understand that there are better ways to solve the expression, it is deployed in production and I don't have the right to modify it.
It works with most of the functions but is throwing errors while using it to find the absolute value of a number.
For example,
DECLARE #formula NVARCHAR(max) = ' abs(-1.5) '
DECLARE #result SQL_VARIANT
EXEC [usp_s_eval_expr] #formula, #result OUTPUT
SELECT #result
This throws the error following error whereas ceiling and round functions work well.
Msg 50000, Level 16, State 1, Procedure usp_s_eval_expr, Line 32 [Batch Start Line 0]
XQuery [query()]: There is no function '{http://www.w3.org/2004/07/xpath-functions}:abs()'
Is there any way to achieve the absolute value of a number order than checking less than 0, the reason why I don't want to check less than is the expression that results in -1.5 is very big, and I don't want to use it twice to achieve the abs functionality.
According to the documentation available by download from https://learn.microsoft.com/en-us/openspecs/sql_standards/MS-SQLSTANDLP/89fb00b1-4b9e-4296-92ce-a2b3f7ca01d2 SQL Server does not support the fn:abs() function.
Also: are you sure about the namespace {http://www.w3.org/2004/07/xpath-functions}. That's from an early draft of XPath 2.0, not the final W3C spec. But I don't think SQL Server ever implemented the final spec anyway.
Another way to get the absolute value might be to convert to a string and strip the minus sign.

T-SQL Error Message 207 When passing values Dynamically

I am attempting to create a stored procedure that allows values to be passed to it, however, when I try to use Dynamic T-SQL I raise an error MSG 207
I know that the error message is supposed to indicate that the column name was misspelled in my statement thanks to the following site:
https://www.tsql.info/error/msg-207-level-16-invalid-column-name.php
This, however, does not make sense as the following hard coded statement works just fine.
INSERT INTO [dbo].[tDriversLicense] (DriversLicensePrefix, DriversLicenseSuffix, DateAdded, DriversLicenseNumber)
VALUES ('shockc', '11653798', GETDATE(), 'GAD4859');
ALTER PROCEDURE [dbo].[spAddDriversLicense]
-- Add the parameters for the stored procedure here
#DriversLicensePrefix NCHAR(8),
#DriversLicenseSuffix NCHAR(10)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #sqlInsertDriversLicense NVARCHAR(MAX)
SET #sqlInsertDriversLicense = 'INSERT INTO [dbo].[tDriversLicense] (DriversLicensePrefix, DriversLicenseSuffix, DateAdded, DriversLicenseNumber)
VALUES (' + #DriversLicensePrefix + ', ' + #DriversLicenseSuffix + ', GETDATE(), GPC4859);'
EXECUTE sp_executesql #sqlInsertDriversLicense
END
I've been spilling over this code for hours and I'm thoroughly confused as to why there is any difference between the two INSERT statements. The values being passed are the same but an error is raised when I attempt to pass them dynamically. How is this raising an error??
I've used some code from this video to attempt to learn how pass Scalar Values dynamically and have had luck in other stored procedures.
https://www.youtube.com/watch?v=RHHKG65WEoU
When working with dynamic strings, select them first, so you can check that the resulting syntax is workable.
You need single quotes in the result, so you need more than single, single quotes, in the code:
declare #DriversLicensePrefix nchar(8) = 'A2345678'
declare #DriversLicenseSuffix nchar(10) = 'abcdefghij'
DECLARE #sqlInsertDriversLicense nvarchar(max)
SET #sqlInsertDriversLicense = 'INSERT INTO [dbo].[tDriversLicense] (DriversLicensePrefix, DriversLicenseSuffix, DateAdded, DriversLicenseNumber)
VALUES (N''' + #DriversLicensePrefix + ''', N''' + #DriversLicenseSuffix + ''', ''' + convert(char(8),GETDATE(),112) + ''', ''GPC4859'');'
select #sqlInsertDriversLicense
+-------------------------------------------------------------------------------------------------------------------+
| result: |
+-------------------------------------------------------------------------------------------------------------------+
| INSERT INTO [dbo].[tDriversLicense] (DriversLicensePrefix, DriversLicenseSuffix, DateAdded, DriversLicenseNumber) |
| VALUES (N'A2345678', N'abcdefghij', '20181109', 'GPC4859'); |
+-------------------------------------------------------------------------------------------------------------------+
NB You should use convert(char(8),getdate(),112) SQL Server will recognize the YYYYMMDD format as a date value regardless of server default settings.
The result see above demonstrates what the insert statement MUST be, note that it it contains several single quotes.
When you are concatenating the SQL statement, you are also dealing with strings, and every part of that has to be contained within single quotes.
So there are multiple needs for single quotes.
And; So you need multiple single quotes throughout out the concatenation, some to help form the SQL statement, and others to be INSIDE that statement.
/* get this into #sql */
select 'Y' as col1;
declare #SQL as nvarchar(max)
set #SQL = N'select ''Y'' as col1;'
select #SQL;
+---------------------+
| #SQL |
+---------------------+
| select 'Y' as col1; |
+---------------------+
In the larger query 2 variables are defined a NCHAR(8) or (10) as you have defined them a Nchar then when inserting data into those you should prefix that input by N
As posted in a comment already there is no need for this dynamic approach at all.
The following code will show a straight and a dynamic approach. Try it out:
USE master;
GO
CREATE DATABASE testDB;
GO
USE testDB;
GO
CREATE TABLE TestTable(SomeContent VARCHAR(100),SomeDate DATETIME,SomeFixString VARCHAR(100));
GO
--This procedure will use the parameters directly. No need for any dynamic SQL:
CREATE PROCEDURE TestStraight(#content VARCHAR(100))
AS
BEGIN
INSERT INTO TestTable(SomeContent,SomeDate,SomeFixString)
VALUES(#content,GETDATE(),'Proc Straight');
END
GO
--this procedure will use real parameters. You should never use parameters in string concatenation. One day you might meet bobby tables...
CREATE PROCEDURE TestDynamic(#content VARCHAR(100))
AS
BEGIN
DECLARE #cmd NVARCHAR(MAX)=
N'INSERT INTO TestTable(SomeContent,SomeDate,SomeFixString)
VALUES(#DynamicContent,GETDATE(),''Proc Dynamic'');'
EXEC sp_executesql #cmd,N'#DynamicContent VARCHAR(100)',#DynamicContent=#content;
END
GO
--Test it
EXEC TestStraight 'yeah!';
EXEC TestDynamic 'oh yeah!';
SELECT * FROM TestTable;
GO
--Clean up
USE master;
GO
--careful with real data!
--DROP DATABASE testDB;

How can i use "Use [database]" transactions within IF statements in SQL?

I'm trying to do something along the lines of:
IF(##SERVERNAME = 'SERVER1')
BEGIN
USE Appt
END
IF(##SERVERNAME = 'SERVER2')
BEGIN
USE ApptDEMO
END
At work, our database for production is "Appt" but the one for test environment is "ApptDEMO."
They're the same thing, but they're just named differently.
It runs fine in the test environment because both "Appt" and "ApptDEMO" exist there (it just doesnt use "Appt").
But in production, it tells me that "ApptDEMO" doesn't exist.
I want to create a script that I don't need to make x amount of different scripts for different environments.
Is this possible?
Try this (with dynamic SQL):
DECLARE #sql nvarchar(4000)
IF (##SERVERNAME = 'SERVER1')
BEGIN
SET #sql = N'USE Appt'
END
ELSE IF (##SERVERNAME = 'SERVER2')
BEGIN
SET #sql = N'USE ApptDEMO'
END
IF (#sql != N'')
BEGIN
EXECUTE sp_executesql #sql
END
Database can't be changed dynamically (USE [DB]) other then making the query dynamic.
Below code may clarify your understanding.
SELECT DB_NAME();
-- Master --Default Database
SELECT ##SERVERNAME
-- SERVER1
DECLARE #USEDB NVARCHAR(MAX) =
CASE ##SERVERNAME WHEN 'SERVER1' THEN 'USE [Appt];'
WHEN 'SERVER2' THEN 'USE [ApptDEMO];'
END -- Same as IF statement
EXEC(#USEDB) -- The database [Appt] will be changed within this batch, not outside.
SELECT DB_NAME();
-- Master --Default Database
DECLARE #MyQuery VARCHAR(MAX) = 'Select DB_NAME();'
DECLARE #UseDBWithQuery VARCHAR(MAX) = #USEDB + #MyQuery
EXEC(#UseDBWithQuery)
-- Appt

dynamic SQL query in SQL Server

declare #text as varchar(100)
declare #rep as varchar
declare #ac as varchar
declare #sub as varchar(4)
declare #stmt as varchar(50)
set #text='1214324324234324'
set #ac='2'
set #rep ='4'
set #sub='#rep'
set #stmt = 'Select Replace('''+#text+''','''+#ac+''','+#sub+')'
print #stmt
--dynamic query execution
exec(#stmt)
I am facing below issue.
Select Replace('1214324324234324','2',#rep) Msg 137, Level 15, State
2, Line 1 Must declare the scalar variable "#rep"
Your error is pretty clear.
set #rep ='4'
set #sub='#rep'
You set a value to #rep and use another variable (#sub) to point at the previous assigned variable #rep. In fact, your dynamic SQL statement is combined like this:
set #stmt = 'Select Replace('''+#text+''','''+#ac+''','+#sub+')'
This will interpreted like this: SELECT REPLACE('1214324324234324','2',#rep)
Your dynamic doesn't know that there is a variable #rep. You need to concat #rep into your dynamic SQL instead of those additional assignment to #sub.
You can use this:
set #stmt = 'Select Replace('''+#text+''','''+#ac+''','+#rep+')'
You need to run the entire statement at once. If you run one line at a time, SQL will forget the variables you previously declared. I took all of your SQL and ran it, and it worked perfectly fine for me.

SQL Server changed my strings before running the query

I try to select some special records contain special characters but SQL Server changes my string characters before it running the query.
For example:
DECLARE #param NVARCHAR(30)
SET #param=N'¤÷þ'--this is my special string that i want to be searched exactly.
DECLARE #TSQL varchar(8000)
SET #TSQL = 'SELECT * FROM MyTable WHERE MyFieldName LIKE %' + #param + '% '
PRINT #TSQL
--EXECUTE (#TSQL)
But in the result(print) I see:
SELECT * FROM MyTable WHERE MyFieldName LIKE '%¤÷þ?%'
As you see some part of string converted to (?) character, this problem cause my SELECT command return null value.
I try to change collation of the database that I run the query to:
SQL_Latin1_General_CP1_CI_AS
It work fine with some special string but it also does not support all of my strings.
So, question is here: how can I tell SQL Server, please don't change my string ascii codes?
Is there any way (or any collation) to say SQL Server that see an string exactly as it is in reality?
PS: I am using SQL Server 2008 R2.
If you have special characters that need to be preserved, use Unicode strings of type NVARCHAR instead of VARCHAR - it's that simple .....
DECLARE #param NVARCHAR(30)
SET #param = N'¤÷þ'--this is my special string that i want to be searched exactly.
DECLARE #TSQL NVARCHAR(4000) -- <=== use NVARCHAR here
SET #TSQL = N'SELECT * FROM MyTable WHERE MyFieldName LIKE %' + #param + N'% '
PRINT #TSQL
Then your special characters will be preserved as entered ....
And as others have pointed out: concatenating together your SQL statements like this is never a good idea - it opens up your code to potential SQL injection attacks. You should use parameterized queries and sp_executesql which allows you to define and supply paramters to your queries.
DECLARE #TSQL varchar(8000)
varchar(8000) cannot represent ¤÷þ. Just keep doing what you're doing with #param; use something NVARCHAR based.
As usr correctly points out, you should really be using sp_executesql and its ability to specify parameters. From the documentation:
DECLARE #IntVariable int;
DECLARE #SQLString nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
/* Build the SQL string one time.*/
SET #SQLString =
N'SELECT BusinessEntityID, NationalIDNumber, JobTitle, LoginID
FROM AdventureWorks2012.HumanResources.Employee
WHERE BusinessEntityID = #BusinessEntityID';
SET #ParmDefinition = N'#BusinessEntityID tinyint';
/* Execute the string with the first parameter value. */
SET #IntVariable = 197;
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#BusinessEntityID = #IntVariable;

Resources