Set variable to result of executed statement in a sproc - sql

Do you have any good concise tutorials about variable syntax? This is part of a sproc:
Set #sql = 'Set ' + #calc + '= SUM(datalength(' + #column_name + '))/2 from ' + #table_name
exec (#sql)
And it doesn't work - I get an Error converting data type varchar to numeric. Here is the simulated example:
DECLARE #calc numeric(18,2)
DECLARE #sql nvarchar(1500), #column_name nvarchar(50), #table_name nvarchar(50)
Set #column_name = 'EID'
Set #table_name = 'CTY_SUPPORTED'
Set #sql = 'Select #calc = SUM(datalength(' + #column_name + '))/2 from ' + #table_name
exec (#sql)
print #calc
I'm interested in attributing to variable #calc the following value: SUM(datalength(column_x))/2 from table_x
Also if you know syntax lessons (preferably not encyclopedias) - many thanks and gooday!

Set #sql = 'Select #calc = SUM(datalength(' + #column_name + '))/2 from ' + #table_name
exec (#sql)

Related

Variable in SQL query syntax

I want to make a simple SQL query like:
SELECT * FROM table WHERE $variable_2 = $variable_1
instead of a default one:
SELECT * FROM table WHERE column_name = $variable_1
It seems like first example doesn't work at all. Is it even possible to modify SQL query syntax in such way?
as this reference answer for:
in link:
Use Variable as SQL column Name in query
answer1:
declare #ColumnName varchar(50)
declare #sql nvarchar(max)
set #ColumnName = 'SalesData_' + convert(varchar(2),datepart(dd,getdate()))
set #sql = 'select ' + #ColumnName + ' from SalesTable'
print #sql
EXEC sp_sqlexec #sql
answer 2:
declare #ColumnName varchar(50)
declare #sql nvarchar(max)
set #ColumnName = 'SalesData_' + convert(varchar(2),datepart(dd,getdate()))
set #sql = 'select ' + #ColumnName + ' from yourschema.SalesTable'
print #sql

Select from list of tables / multiple tables with nested query - MS SQL

Not sure if this has an easy answer, but I'm basically trying to do this:
select id
from (select table_name from information_schema.columns where column_name = 'id')
where id = 1234
So passing in a list of tables into the FROM.
I'm trying to check all tables where this column exists if they have a matching value for 1234.
And without typing 31 times, select from table1, select from table2, etc etc
And without doing a bunch of joins.
possible?
I wrote this stored procedure.
It SUCKS I know, I've never written anything in tsql (teesquill?) before, and my goal was just to get something that works.
// find all occurrences of value in DB
USE [your db here]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[usp_query] (
#value NVARCHAR(128),
#colName NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #sql NVARCHAR(MAX);
-- DECLARE #tables NVARCHAR(MAX);
DECLARE #tabName NVARCHAR(MAX);
-- DECLARE #colName NVARCHAR(MAX);
DECLARE #count INT;
-- construct SQL
--SET #tables = N'SELECT Table_name FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME LIKE "yourcollumn"'
DECLARE tabs CURSOR FOR SELECT table_name FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME LIKE 'yourcollumn'
OPEN tabs
FETCH NEXT FROM tabs INTO #tabName
WHILE ##fetch_status = 0
BEGIN
--SET #count = N'SELECT count ( ' + #colName + ' ) FROM ' + #tabName + ' where ' + #colName + ' = ' + #value
DECLARE #SQLString NVARCHAR(500);
DECLARE #ParmDefinition NVARCHAR(500);
DECLARE #varOut NVARCHAR(25);
SET #SQLString = N'SELECT #count = count ( ' + #colName + ' ) FROM ' + #tabName + ' where ' + #colName + ' = ' + #value;
SET #ParmDefinition = N'#count NVARCHAR(25) OUTPUT';
EXECUTE sp_executesql #SQLString
,#ParmDefinition
,#count = #varOut OUTPUT;
SET #sql = N'SELECT ' + #colName + ' FROM ' + #tabName + ' where yourcollumn = ' + #value;
IF #varOut > 0
SELECT #tabName AS 'value found in table'
--EXEC sp_executesql #sql
FETCH NEXT FROM tabs INTO #tabName
END
CLOSE tabs
END;

Temporary tables in Stored procedure are not accesing data?

This is My code
create proc TEMP
AS
BEGIN
DECLARE #SQL nvarchar(4000)
IF OBJECT_ID(N'tempdb..#TEMP1') IS NOT NULL
DROP TABLE #TEMP1;
SET #SQL ='SELECT CUSTOMERS,AREA,HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL +'INTO #TEMP1'+CHAR(10)
SET #SQL = #SQL +'FROM NEW'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
IF OBJECT_ID(N'tempdb..#TEMP2') IS NOT NULL
DROP TABLE #TEMP2;
SET #SQL ='SELECT CUSTOMERS,AREA,VEHICELS'+CHAR(10)
SET #SQL = #SQL +'INTO #TEMP2'+CHAR(10)
SET #SQL = #SQL +'FROM OLD'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
IF OBJECT_ID(N'tempdb..#TEMP3') IS NOT NULL
DROP TABLE #TEMP3;
SET #SQL ='SELECT 0.VEHICELS,C.HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL +'INTO #TEMP3'+CHAR(10)
SET #SQL = #SQL +'FROM #TEMP1 C'+CHAR(10)
SET #SQL = #SQL +'INNER JOIN #TEMP2 O '+CHAR(10)
SET #SQL = #SQL +'on C.CUSTOMERS=O.CUSTOMERS'+CHAR(10)
SET #SQL = #SQL +'AND C.AREA=O.AREA'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
END
My error:
Msg 208, Level 16, State 0, Line 1
Invalid object name '#TEMP1'.
First TEMP1 and TEMP2 are working well, but when it comes to TEMP3 it doesn't access TEMP1 where the data is present
Can you guys check this confusing problem ???
DECLARE #sql varchar(max)
SET #sql = 'CREATE TABLE ##T1 (Col1 varchar(20))'
EXEC(#sql)
INSERT INTO ##T1 (Col1) VALUES ('This will work.')
SELECT * FROM ##T1
DO WE GET ANY PROBLEMS IN FUTURE IF WE USE GLOBALTEMPORARY TABLES???
once the exec finishes executing the #temp table is deleted
maybe if you try using a wider scope, it could succeed, I don't know.
try something like this.
create proc TEMP
AS
BEGIN
DECLARE #now datetime;
DECLARE #TempTableTableSuffix sysname
SET #now = GETDATE()
select #TempTableTableSuffix = CONVERT(VARCHAR, CONVERT(int,RAND(DATEPART(MILLISECOND,#now)+1000*(DATEPART(SECOND,#now)+60*(DATEPART(MINUTE,#now)+60*DATEPART(HOUR,#now)))) * 100000000))
DECLARE #SQL nvarchar(4000)
SET #SQL ='SELECT CUSTOMERS,AREA,HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL +'INTO ##TEMP1' + #TempTableTableSuffix + CHAR(10)
SET #SQL = #SQL +'FROM NEW'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
SET #SQL ='SELECT CUSTOMERS,AREA,VEHICELS'+CHAR(10)
SET #SQL = #SQL +'INTO ##TEMP2' + #TempTableTableSuffix + CHAR(10)
SET #SQL = #SQL +'FROM OLD'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
SET #SQL ='SELECT 0.VEHICELS,C.HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL +'INTO ##TEMP3'+CHAR(10)
SET #SQL = #SQL +'FROM ##TEMP1' + + #TempTableTableSuffix + ' C'+CHAR(10)
SET #SQL = #SQL +'INNER JOIN #TEMP2'+ #TempTableTableSuffix + ' O '+CHAR(10)
SET #SQL = #SQL +'on C.CUSTOMERS=O.CUSTOMERS'+CHAR(10)
SET #SQL = #SQL +'AND C.AREA=O.AREA'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)
END
anyway, I think you don't need dynamic SQL for this.
Use single EXEC -
DECLARE #SQL nvarchar(MAX)
IF OBJECT_ID(N'tempdb..#TEMP1') IS NOT NULL
DROP TABLE #TEMP1;
IF OBJECT_ID(N'tempdb..#TEMP2') IS NOT NULL
DROP TABLE #TEMP2;
IF OBJECT_ID(N'tempdb..#TEMP3') IS NOT NULL
DROP TABLE #TEMP3;
SET #SQL = ' SELECT CUSTOMERS,AREA,HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL + ' INTO #TEMP1'+CHAR(10)
SET #SQL = #SQL + ' FROM NEW'+CHAR(10)
SET #SQL = #SQL + ' SELECT CUSTOMERS,AREA,VEHICELS'+CHAR(10)
SET #SQL = #SQL + ' INTO #TEMP2'+CHAR(10)
SET #SQL = #SQL + ' FROM OLD'+CHAR(10)
SET #SQL = #SQL + ' SELECT 0.VEHICELS,C.HOUSEHOLDS'+CHAR(10)
SET #SQL = #SQL + ' INTO #TEMP3'+CHAR(10)
SET #SQL = #SQL + ' FROM #TEMP1 C'+CHAR(10)
SET #SQL = #SQL + ' INNER JOIN #TEMP2 O '+CHAR(10)
SET #SQL = #SQL + ' on C.CUSTOMERS=O.CUSTOMERS'+CHAR(10)
SET #SQL = #SQL + ' AND C.AREA=O.AREA'+CHAR(10)
PRINT(#SQL)
EXEC (#SQL)

How do I query a value dynamically in T-SQL?

For whatever reason, I can't seem to get a value out dynamically from SQL.
declare #SQL nvarchar(max)
declare #FieldName nvarchar(255)
declare #FieldValue nvarchar(max)
select #SQL = 'SELECT TOP 1 ' + #fieldname
+' FROM MyTable WHERE CM_CASE_YEAR = ' + LEFT(#ClaimNumber, 2)
+' AND CM_CASE_NUMBER = ' + RIGHT(#ClaimNumber, 6)
exec sp_executesql #sql, #FieldValue OUTPUT
select #FieldName + ' - ' + #FieldValue
When I run the #SQL query in another window, it displays one column with one value.
But, unfortunately when I try this, #FieldValue always comes back NULL.
Did I miss something the day they taught sp_executesql? Obviously! But what?
See this example
DECLARE #SQL NVARCHAR(MAX)
DECLARE #FieldName sysname = 'name'
DECLARE #FieldValue NVARCHAR(MAX)
SELECT #SQL = 'SELECT TOP 1
#FieldValue =' + QUOTENAME(#FieldName) + ' FROM sys.objects'
EXEC sp_executesql #SQL,
N'#FieldValue nvarchar(max) OUTPUT',
#FieldValue =#FieldValue OUTPUT
SELECT #FieldName + ' - ' + #FieldValue
sp_executesql returns (generates) a resultset. #FieldValue is meaningless in the code above - sp_executesql won't put any value into that variable.

How do I do a simple 'Find and Replace" in MsSQL?

Question is pretty self explanitory. I want to do a simple find and replace, like you would in a text editor on the data in a column of my database (which is MsSQL on MS Windows server 2003)
The following query replace each and every a character with a b character.
UPDATE
YourTable
SET
Column1 = REPLACE(Column1,'a','b')
WHERE
Column1 LIKE '%a%'
This will not work on SQL server 2003.
like so:
BEGIN TRANSACTION;
UPDATE table_name
SET column_name=REPLACE(column_name,'text_to_find','replace_with_this');
COMMIT TRANSACTION;
Example: Replaces <script... with <a ... to eliminate javascript vulnerabilities
BEGIN TRANSACTION; UPDATE testdb
SET title=REPLACE(title,'script','a'); COMMIT TRANSACTION;
This pointed me in the right direction, but I have a DB that originated in MSSQL 2000 and is still using the ntext data type for the column I was replacing on. When you try to run REPLACE on that type you get this error:
Argument data type ntext is invalid for argument 1 of replace
function.
The simplest fix, if your column data fits within nvarchar, is to cast the column during replace. Borrowing the code from the accepted answer:
UPDATE YourTable
SET Column1 = REPLACE(cast(Column1 as nvarchar(max)),'a','b')
WHERE Column1 LIKE '%a%'
This worked perfectly for me. Thanks to this forum post I found for the fix. Hopefully this helps someone else!
The following will find and replace a string in every database (excluding system databases) on every table on the instance you are connected to:
Simply change 'Search String' to whatever you seek and 'Replace String' with whatever you want to replace it with.
--Getting all the databases and making a cursor
DECLARE db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name NOT IN ('master','model','msdb','tempdb') -- exclude these databases
DECLARE #databaseName nvarchar(1000)
--opening the cursor to move over the databases in this instance
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #databaseName
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #databaseName
--Setting up temp table for the results of our search
DECLARE #Results TABLE(TableName nvarchar(370), RealColumnName nvarchar(370), ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE #SearchStr nvarchar(100), #ReplaceStr nvarchar(100), #SearchStr2 nvarchar(110)
SET #SearchStr = 'Search String'
SET #ReplaceStr = 'Replace String'
SET #SearchStr2 = QUOTENAME('%' + #SearchStr + '%','''')
DECLARE #TableName nvarchar(256), #ColumnName nvarchar(128)
SET #TableName = ''
--Looping over all the tables in the database
WHILE #TableName IS NOT NULL
BEGIN
DECLARE #SQL nvarchar(2000)
SET #ColumnName = ''
DECLARE #result NVARCHAR(256)
SET #SQL = 'USE ' + #databaseName + '
SELECT #result = MIN(QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME))
FROM [' + #databaseName + '].INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = ''BASE TABLE'' AND TABLE_CATALOG = ''' + #databaseName + '''
AND QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME) > ''' + #TableName + '''
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME)
), ''IsMSShipped''
) = 0'
EXEC master..sp_executesql #SQL, N'#result nvarchar(256) out', #result out
SET #TableName = #result
PRINT #TableName
WHILE (#TableName IS NOT NULL) AND (#ColumnName IS NOT NULL)
BEGIN
DECLARE #ColumnResult NVARCHAR(256)
SET #SQL = '
SELECT #ColumnResult = MIN(QUOTENAME(COLUMN_NAME))
FROM [' + #databaseName + '].INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(''[' + #databaseName + '].' + #TableName + ''', 2)
AND TABLE_NAME = PARSENAME(''[' + #databaseName + '].' + #TableName + ''', 1)
AND DATA_TYPE IN (''char'', ''varchar'', ''nchar'', ''nvarchar'')
AND TABLE_CATALOG = ''' + #databaseName + '''
AND QUOTENAME(COLUMN_NAME) > ''' + #ColumnName + ''''
PRINT #SQL
EXEC master..sp_executesql #SQL, N'#ColumnResult nvarchar(256) out', #ColumnResult out
SET #ColumnName = #ColumnResult
PRINT #ColumnName
IF #ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC
(
'USE ' + #databaseName + '
SELECT ''' + #TableName + ''',''' + #ColumnName + ''',''' + #TableName + '.' + #ColumnName + ''', LEFT(' + #ColumnName + ', 3630)
FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE ' + #ColumnName + ' LIKE ' + #SearchStr2
)
END
END
END
--Declaring another temporary table
DECLARE #time_to_update TABLE(TableName nvarchar(370), RealColumnName nvarchar(370))
INSERT INTO #time_to_update
SELECT TableName, RealColumnName FROM #Results GROUP BY TableName, RealColumnName
DECLARE #MyCursor CURSOR;
BEGIN
DECLARE #t nvarchar(370)
DECLARE #c nvarchar(370)
--Looping over the search results
SET #MyCursor = CURSOR FOR
SELECT TableName, RealColumnName FROM #time_to_update GROUP BY TableName, RealColumnName
--Getting my variables from the first item
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #t, #c
WHILE ##FETCH_STATUS = 0
BEGIN
-- Updating the old values with the new value
DECLARE #sqlCommand varchar(1000)
SET #sqlCommand = '
USE ' + #databaseName + '
UPDATE [' + #databaseName + '].' + #t + ' SET ' + #c + ' = REPLACE(' + #c + ', ''' + #SearchStr + ''', ''' + #ReplaceStr + ''')
WHERE ' + #c + ' LIKE ''' + #SearchStr2 + ''''
PRINT #sqlCommand
BEGIN TRY
EXEC (#sqlCommand)
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE()
END CATCH
--Getting next row values
FETCH NEXT FROM #MyCursor
INTO #t, #c
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
DELETE FROM #time_to_update
DELETE FROM #Results
FETCH NEXT FROM db_cursor INTO #databaseName
END
CLOSE db_cursor
DEALLOCATE db_cursor
Note: this isn't ideal, nor is it optimized
If you are working with SQL Server 2005 or later there is also a CLR library available at http://www.sqlsharp.com/ that provides .NET implementations of string and RegEx functions which, depending on your volume and type of data may be easier to use and in some cases the .NET string manipulation functions can be more efficient than T-SQL ones.