Plpgsql: How can i perform the following task in plpgsql? - postgresql

--Syntax in SQL Server
SET #InnerQuery = #InnerQuery + N'SELECT * from [' + #TableName + '] UNION ALL';
--Here i am trying in plpgsql for above query.
innerquery:= innerquery UNION ALL select * from '%',TableName; --Not in working state

Try this:
execute innerQuery || ' union all select * from "'
|| tableName || '"';

Related

Getting Error With GROUP BY when Converting Query to Dynamic SQL

I'm trying to convert the following query to dynamic SQL to allow for variations:
UPDATE T
SET SumCount = J.SUM
FROM #temp T
JOIN (SELECT Count_99221 + COUNT_99222 + Count_99223 [SUM], t2.userID
FROM #temp t2
GROUP BY t2.userID, Count_99221 + COUNT_99222 + Count_99223
) J ON T.userID = J.UserID
This is what I have for the Dynamic SQL:
DECLARE #sql3 nvarchar(2000) =
'UPDATE T ' +
'SET SumCount = J.SumOfColumns ' +
'FROM #temp T ' +
'JOIN (SELECT ' + #columnSumString + ' [SumOfColumns], t2.userID ' +
'FROM #temp t2 ' +
'GROUP BY t2.userID, ' + #columnSumString +
' ) J ON T.userID = J.UserID'
EXEC sp_executesql #sql3
I am receiving the following error only when I run the query as Dynamic SQL:
Each GROUP BY expression must contain at least one column that is not
an outer reference.
Can somebody help explain why this is happening? I am new to Dynamic SQL so I'm not privy to any limitations for running queries this way.
Thank you in advance.
EDIT:
The variable #columnString is a string made by concatenating several other column names, created in the following way:
DECLARE #Cursor Cursor
DECLARE #code varchar(20)
DECLARE #ID INT
SET #cptCursor = CURSOR FOR
SELECT * FROM dbo.Split(#UserInput,CHAR(44))
OPEN #cptCursor
FETCH NEXT FROM #cptCursor INTO #ID, #code
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #colName varchar(50) = 'Count_' + cast(#code as varchar(10))
DECLARE #sql nvarchar(50) = 'ALTER TABLE #temp ADD ' + #colName + ' int'
EXEC sp_executesql #sql
--Code that adds values to each column that is created.....
SET #columnSumString = #colName + ' + ' + #columnSumString
--SET #columnSumString = #code + ' + ' + #columnSumString
FETCH NEXT FROM #cptCursor INTO #ID, #code
END
CLOSE #Cursor
DEALLOCATE #Cursor
SET #columnSumString = SUBSTRING(#columnSumString,1,LEN(#columnSumString)-2)
SELECT #columnSumString
The user input is a comma separated string. "Count_99221 + COUNT_99222 + Count_99223" is just one example of columns created from the user input "99221, 99222, 99223".
I also realized I was concatenating the #code variable into #columnSumString instead of #colName. Now when I run the query I don't get the error (even though I don't understand how the above error message relates to that mistake) but every value of SumCount is NULL.
IMHO you must re-write your query as follow:
UPDATE #temp
SET SumCount =
(SELECT Count_99221 + COUNT_99222 + Count_99223
FROM #temp t2
WHERE t2.userID = #temp.userID)
So the dynamic SQL will become:
DECLARE #columnString varchar(200)
SET #columnString = Count_99221 + COUNT_99222 + Count_99223
DECLARE #sql3 nvarchar(2000) =
N'UPDATE #temp ' +
'SET SumCount = (SELECT ' + #columnString +
' FROM #temp t2 WHERE t2.userID = #temp.userID)'
EXEC sp_executesql #sql3

How to create view for all tables in database?

I want to make views from all tables already exist in database that’s hard task to catch the tables one by one and make create view XXXX as select * from Table_name .I find something that it is possible with cursor and the code is :
DECLARE #TableName sysname
DECLARE #ColumnCount INT
DECLARE #ColumnID INT
DECLARE #SelectColumn NVARCHAR(500)
DECLARE #sql NVARCHAR(max) = ''
DECLARE QUERYINFO CURSOR FOR
SELECT
t.name AS TableName,
ccount.ColumnCount,
c.column_id AS ColumnID,
CASE WHEN c.column_id <> ccount.ColumnCount
THEN c.name + ', '
ELSE c.name
END AS SelectColumn
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id=c.object_id
INNER JOIN (
SELECT object_id,COUNT(*) AS ColumnCount
FROM sys.columns
GROUP BY object_id
) ccount ON t.object_id = ccount.object_id
ORDER BY t.Name,c.column_id
OPEN QUERYINFO
FETCH NEXT FROM QUERYINFO INTO #TableName,#ColumnCount,#ColumnID,#SelectColumn
WHILE ##FETCH_STATUS = 0
BEGIN
IF #ColumnID = 1
BEGIN
SET #sql = 'CREATE VIEW v_' + #TableName + ' AS SELECT ' + #SelectColumn
END
ELSE
BEGIN
SET #sql = #sql + #SelectColumn
END
IF #ColumnID = #ColumnCount
BEGIN
SET #sql = #sql + ' FROM ' + #TableName
EXEC sys.sp_executesql #sql
SET #sql = ''
END
FETCH NEXT FROM QUERYINFO INTO #TableName,#ColumnCount,#ColumnID,#SelectColumn
END
CLOSE QUERYINFO
DEALLOCATE QUERYINFO
but it has error and I don't know how solve it
This is what I would do with dynamic SQL; checking first to see if the view exists, then creating it with all of the columns (not by using SELECT * FROM...).
DECLARE #SQL nvarchar(MAX)
SET #SQL = N''
SELECT
#SQL = #SQL +
N'IF EXISTS(SELECT 1 FROM sys.objects WHERE name = N''v_' + t.name + N''' AND type = N''V'') BEGIN DROP VIEW [v_' + t.name + '] END CREATE VIEW [v_' + t.name + N'] AS SELECT ' +
STUFF(
(SELECT N',' + c.name
FROM
sys.columns AS c
WHERE
c.OBJECT_ID = t.OBJECT_ID
ORDER BY
column_id
FOR XML PATH(''), TYPE).value('.',N'nvarchar(max)')
,1,1,N'')
+ N' FROM [' + t.name + N'];'
FROM
sys.tables AS t
EXEC sp_executesql #SQL

the multi-part identifier "#tmpFullname.Item" could not be bound."

The following code is supposed to take a string that may or may not be comma delimited and put it into a table (#tmpFullanme) that part works flawlessly. The second part is supposed return all the values that are LIKE / NOT LIKE with or without % symbols based on what is input. The error that I am getting is "the multi-part identifier "#tmpFullname.Item" could not be bound." The best guess I have is that it may be out of scope?
DROP PROCEDURE uspJudgments;
GO
CREATE PROCEDURE uspJudgments
#fullName varchar(100), #SrchCriteria1 varchar(15), #SrchCriteria2 varchar(15), #qualifier varchar(10)
AS
BEGIN
SELECT *
INTO #tmpFullname
FROM dbo.DelimitedSplit8K(#fullName, ',')
DECLARE #Query NVarChar(1024)
SET #Query = 'SELECT d.*' + ' FROM defendants_ALL d, #tmpFullname' +
' WHERE d.combined_name' + ' ' + #qualifier + ' ' + '''' + #SrchCriteria1 + '''' + ' + ' + '''' + #tmpFullname.Item + '''' + ' + ' + '''' + #SrchCriteria2 + ''''
END
EXEC sp_executesql #Query
PRINT(#Query)
IF OBJECT_ID('#tmpFullname', 'U') IS NOT NULL
DROP TABLE #tmpFullname
EXEC uspJudgments #qualifier = 'LIKE', #fullName = 'johnson', #SrchCriteria1 = '%', #SrchCriteria2 = '%'
Cannot get to the PRINT output as "the multi-part identifier "#tmpFullname.Item" could not be bound." If I change #tmpFullname.Item to '#tmpFullname.Item it goes through and returns nothing but it shows that the query is correct minus the issue with that table.
SELECT d.* FROM defendants_ALL d, #tmpFullname WHERE d.combined_name LIKE '%' + '#tmpFullname.Item' + '%'
Please note that until I made this into a dynamic query so I can change the statement from LIKE to IN etc it worked very well.
I set up a full test to get the proper script to get you your desired results. I also have a SQL Fiddle showing how this works. Note You will want to run EXECUTE sp_executesql #Query inside the stored procedure
ALTER PROCEDURE uspJudgments #fullName varchar(100)
, #SrchCriteria1 varchar(15)
, #SrchCriteria2 varchar(15)
, #qualifier varchar(10)
AS
BEGIN
--Simulates your split function
SELECT *
INTO #tmpFullName
FROM
(
SELECT 'firstTest' AS Item
UNION ALL SELECT 'secondTest'
UNION ALL SELECT 'NotThere'
) AS t;
DECLARE #Query NVARCHAR(1024);
SELECT #Query = 'SELECT d.* '
+ ' FROM defendants_ALL d '
+ ' CROSS JOIN #tmpFullName AS t '
+ ' WHERE d.combined_name' + ' ' + #qualifier + ' '
+ '''' + #SrchCriteria1 + ''''
+ ' + ' + 't.Item' + ' + ' + '''' + #SrchCriteria2 + '''';
EXECUTE sp_executesql #Query;
END
EXECUTE uspJudgments
#fullName = 'does not matter'
, #SrchCriteria1 = '%'
, #SrchCriteria2 = '%'
, #qualifier = 'LIKE';
You have to use the tempdb prefix in this case
insert into tempdb..#TABLENAME
and
set #query = 'select * from tempdb..#TABLENAME'
Well, After my last answer i have found several things..
When i look into your procedure you start with the "BEGIN", next you do a insert into the "#tmpFullName" table, your declare the "#Query" variable and create a select statement.
After that you do and "END" with logic after it. You do the "sp_executesql" after that you drop the temptable and you do and EXEC of the current procedure..
The Structure isn't all that readable, sorry to tell you. So maybe you go there first.
Beside a strange structure you are using the "#tmpFullName.Item" in some dynamic SQL as a parameter, while it is declared inside the SQL query it self. So you have to do something like this :
SET #Query = 'SELECT d.*' + ' FROM defendants_ALL d, #tmpFullname' +
' WHERE d.combined_name' + ' ' + #qualifier + ' ' + '''' + #SrchCriteria1 + '''' + ' + ' + ' #tmpFullname.Item ' + ' + ' + '''' + #SrchCriteria2 + ''''
Where the "#tmpFullName.Item" resides insde the code, not as a parameter. But then again, what are you trying to achieve here? To answer this completly we have to know what the other variables are. Your structure isn't telling me what are trying to achieve..
I really can't make any more out of it...

Applying T-SQL...Back to Basics

IM very new to TSQL and am getting my head around stored proceedures etc.
I am using the Code to find a value within one table in my data base, but im not too sure how i would use this code...
Do i need to replace all #* with my relevant table or column name or simply compy paste and execute
Thanks for the help
How do I find a value anywhere in a SQL Server Database?
CREATE PROC SearchAllTables
(#SearchStr nvarchar(100) ) AS BEGIN
-- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved.
-- Purpose: To search all columns of all tables for a given search string
-- Written by: Narayana Vyas Kondreddi
-- Site: http://vyaskn.tripod.com
-- Tested on: SQL Server 7.0 and SQL Server 2000
-- Date modified: 28th July 2002 22:50 GMT
DECLARE #Results
TABLE(ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE #TableName nvarchar(256), #ColumnName nvarchar(128), #SearchStr2 nvarchar(110)
SET #TableName = ''
SET #SearchStr2 = QUOTENAME('%' + #SearchStr + '%','''')
WHILE #TableName IS NOT NULL
BEGIN
SET #ColumnName = ''
SET #TableName = (SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > #TableName
AND OBJECTPROPERTY(OBJECT_ID(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)), 'IsMSShipped') = 0)
WHILE (#TableName IS NOT NULL)
AND (#ColumnName IS NOT NULL)
BEGIN
SET #ColumnName =(SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(#TableName, 2)
AND TABLE_NAME = PARSENAME(#TableName, 1)
AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
AND QUOTENAME(COLUMN_NAME) > #ColumnName)
IF #ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC
('SELECT ''' + #TableName + '.' + #ColumnName + ''', LEFT(' + #ColumnName + ', 3630)
FROM ' + #TableName + ' (NOLOCK) ' + ' WHERE ' + #ColumnName + ' LIKE ' + #SearchStr2)
END
END
END
SELECT ColumnName, ColumnValue
FROM #Results
END
Well, to answer your question:
First you have to copy the code to a query window an run it.
That will create the stored procedure.
Now you can call the stored procedute by calling:
EXEC SearchAllTables 'a string of your choice'
Note that you will only get hits from text columns (like 'char', 'varchar', 'nchar', 'nvarchar').

How to add variables in Dynamic Sql, not concatenate them?

I have the following dynamic sql statement where I want to add #StartRowIndex + #MaximumRows and subtract 1 from it. I am unclear on where to put the single quotes in the statement. Here it is:
SET #sql = #sql + ' SELECT *
FROM
LicenseInfo
WHERE RowNum
BETWEEN ' + #StartRowIndex + ' AND ' +
'(' + #StartRowIndex + #MaximumRows + ')' - 1
+ ' ORDER BY cnt desc'
Create new variable #EndRowIndex and calculate it before you construct the dynamic sql statement.
Something like:
DECLARE #EndRowIndex int
SET #EndRowIndex = #StartRowIndex + #MaximumRows - 1
SET #sql = #sql + ' SELECT *
FROM
LicenseInfo
WHERE RowNum
BETWEEN ' + #StartRowIndex + ' AND ' + #EndRowIndex
+ ' ORDER BY cnt desc'
You need to cast the int parameters into varchar
SET #sql = #sql + ' SELECT *
FROM
LicenseInfo
WHERE RowNum
BETWEEN ' + #StartRowIndex + ' AND ' +
'(' + CAST(#StartRowIndex as varchar(10)) + CAST(#MaximumRows as varchar(10)) + ') - 1
ORDER BY cnt desc'
Declare a variable, do the calculation and CAST it to varchar when generating the SQL statement
DECLARE #LastRowIndex int
SET #LastRowIndex = #StartRowIndex + #MaximumRows - 1
SET #sql = #sql + '
SELECT *
FROM LicenseInfo
WHERE 1=1
AND RowNum BETWEEN ' + CAST (#StartRowIndex as VarChar) +
' AND ' + CAST (#LastRowIndex as VarChar)
+ ' ORDER BY cnt DESC'
You have to cast in order to let SQL Server concatenate string values, otherwise it will try to convert the nVarChar to number and try to add them as numerics.