Why SQL Server doesn't see database - sql-server

I'm implementing full-text search on SQL Server 2014. I've added dbo.Blocks table like dbo.Articles in the 4th step in this tutorial http://www.mikesdotnetting.com/article/298/implementing-sql-server-full-text-search-in-an-asp-net-mvc-web-application-with-entity-framework
And I have simplified Search procedure for my purposes:
CREATE PROCEDURE Search
#SearchTerm varchar(8000),
#CurrentPage int = 1,
#PageSize int = 20
AS
BEGIN
DECLARE #NearPredicate varchar(8000),
#AndPredicate varchar(8000),
#TotalRecords int
SELECT
#NearPredicate = COALESCE(#NearPredicate + ' NEAR ', '') + items
FROM
dbo.Split(#SearchTerm, ' ')
LEFT JOIN
sys.fulltext_system_stopwords ON items = stopword
WHERE
stopword IS NULL
SET #AndPredicate = REPLACE(#NearPredicate, 'NEAR', 'AND')
SET #NearPredicate = '(' + #NearPredicate + ')'
SET #TotalRecords = (
SELECT
COUNT(*)
FROM
AbstractBuildBlocks
WHERE CONTAINS(*, #AndPredicate )
)
SELECT a.SiteId,
a.Content,
ct.Rank,
#TotalRecords AS TotalRecords
FROM
AbstractBuildBlocks a
INNER JOIN CONTAINSTABLE (Blocks, *, #NearPredicate ) AS ct ON a.Id = ct.[Key]
ORDER BY
ct.RANK DESC
OFFSET (#CurrentPage - 1) * #PageSize ROWS FETCH NEXT #PageSize ROWS only
END
I try to test this in SQL Server Management Studio: press new query, print EXEC Search #SearchTerm="sample", #CurrentPage = 1 and hit !Execute.
There are two problems:
Small: SQL Server Management Studio underlines Search in my query and says:
Couldn't find stored procedure 'Search'
Big: server when executing query throws an error:
Msg 208, Level 16, State 1, Procedure Search, Line 34
Invalid object name 'Blocks'.
on line 34:
FROM dbo.Split(#SearchTerm, ' ') /*line 34*/
I found it strange because I've created database dbo.Blocks and in Split Function I even don't use this table.
Don't know if it important but dbo.Split is underlined with red, message: Invalid object name, but despite this procedure has been successfully created and stored.
And the last I've just try to replace Blocks with dbo.Blocks
here:
FROM
AbstractBuildBlocks a
INNER JOIN CONTAINSTABLE (Blocks, *, #NearPredicate ) AS ct ON a.Id = ct.[Key]
and recompile procedure - the error now:
Msg 208, Level 16, State 1, Procedure Search, Line 34
Invalid object name 'dbo.Blocks'. /instead of blocks/
UPDATE I've used this
SELECT '['+SCHEMA_NAME(schema_id)+'].['+name+']'
AS SchemaTable
FROM sys.tables
There is no Blocks table in result. And this is Blocks's properties

You're trying to use the Blocks object as a table but it's the name of your full text catalog. If you look at the CONTAINSTABLE documentation, the first parameter is a table that has been full text indexed. Should that first parameter be dbo.Search?

Related

Identify how many times a string exists on a stored procedure in SQL Server

I have to search the occurrence of a particular string inside all available stored procedures in SQL Server. I know that we can get this by using the below query.
SELECT OBJECT_NAME(OBJECT_ID) PrcName
FROM sys.sql_modules
WHERE DEFINITION LIKE '%SearchStr%'
But is there a way we can find out how many times the particular string is available in each stored procedure? This is for estimating the effort modifying the stored procedures.
Any help will be much appreciated.
This will work as tested:
;WITH cte as
(
SELECT OBJECT_NAME(OBJECT_ID) PrcName, OBJECT_ID
FROM sys.sql_modules
WHERE DEFINITION LIKE '%tblNDT%')
select t1.PrcName, (LEN(Definition) - LEN(replace(Definition,'tblNDT',''))) / LEN('tblNDT') Cnt
from cte t1
INNER JOIN sys.sql_modules t2 on t1.object_id = t2.object_id
An easy way of checking how many times something occurs is to take the initial length, replace your string with blanks, recheck the length, and divide by the length of your string:
DECLARE #sentence VARCHAR(100)
DECLARE #word VARCHAR(100)
SET #word = 'Cool'
SET #sentence = 'This cool sentence is really cool. Cool!'
DECLARE #wordlen INT = (SELECT LEN(#word))
--Original sentence and length
SELECT #sentence AS setencelen
SELECT LEN(#sentence) AS origsentence
--With word removed
SELECT REPLACE(#sentence, 'cool', '') AS shortenedsentence
SELECT LEN(REPLACE(#sentence, 'cool', '')) AS shortenedlen
SELECT LEN(#sentence) - LEN(REPLACE(#sentence, 'cool', '')) AS diffinlength
SELECT (LEN(#sentence) - LEN(REPLACE(#sentence, 'cool', ''))) / #wordlen AS occurrences
I have seen this work in some cases and not in others. If you have a bunch of comments that contain the same string, it will count incorrectly.
I have found a solution for this.
DECLARE #cnt AS INT= 1
DECLARE #SearchStr VARCHAR(MAX) = 'SearchText'
;WITH CTE_SearchStr1
AS
(
SELECT #cnt Cnt, #SearchStr SearchStr UNION ALL
SELECT Cnt + 1, #SearchStr+'%'+SearchStr FROM CTE_SearchStr1
),
CTE_SearchStr2
AS
(
SELECT TOP 100 * FROM CTE_SearchStr1
)
SELECT OBJECT_NAME(OBJECT_ID) ObjectName, MAX(cnt) cnt FROM sys.sql_modules a INNER JOIN CTE_SearchStr2 b ON
a.definition LIKE '%'+b.SearchStr+'%'
GROUP BY OBJECT_NAME(OBJECT_ID) ORDER BY 2 DESC
Only problem with the above query is that I can not search for more that 100 times. It will throw the below exception
Msg 530, Level 16, State 1, Line 3 The statement terminated. The
maximum recursion 100 has been exhausted before statement completion.
In my scenario, the number of occurrences are less than 100, but is there a way to overcome this error?

Including list of params in OPENQUERY

I'm trying to get the values from an external Database server executing the following code:
DECLARE #TSQL VARCHAR(8000), #VAR CHAR(2)
DECLARE #Prefixos VARCHAR(MAX);
WITH cte AS
(
SELECT DISTINCT prefixo
FROM ARH.arh.UorPos
)
SELECT #Prefixos = COALESCE(#Prefixos + ', ', '') + prefixo
FROM cte
ORDER BY prefixo
--SELECT #Prefixos --print a list of values separated by comma. eg.: 1, 2, 3
SELECT #TSQL = 'SELECT * FROM OPENQUERY(DICOI_LINKEDSERVER,''SELECT * FROM ssr.vw_sigas_diage where cd_prf_responsavel in (''''' + #Prefixos + ''''''') order by cd_prf_responsavel, codigo'
EXEC (#TSQL)
But I'm getting:
OLE DB provider "MSDASQL" for linked server "DICOI_LINKEDSERVER" returned message "ERRO: syntax error at the end of input;
No query has been executed with that handle".
Msg 7350, Level 16, State 2, Line 1
Cannot get the column information from OLE DB provider "MSDASQL" for linked server "DICOI_LINKEDSERVER".
I've researched the above links to try to resolve it:
How to concatenate text from multiple rows into a single text string in SQL server?
including parameters in OPENQUERY
Join query result to a single line of values separated by comma [duplicate]
Can anyone help me to resolve it ?
Thanks in advance.
Before running your query with EXEC, it's best to just check first how the generated SQL string will look like.
For example by selecting the variable
DECLARE #TSQL VARCHAR(8000), #VAR CHAR(2)
DECLARE #Prefixos VARCHAR(MAX);
WITH cte AS
(
SELECT DISTINCT prefixo
FROM (values ('1'),('2'),('3')) q(prefixo)
)
SELECT #Prefixos = COALESCE(#Prefixos + ', ', '') + prefixo
FROM cte
ORDER BY prefixo
SELECT #TSQL = 'SELECT * FROM OPENQUERY(DICOI_LINKEDSERVER,''SELECT * FROM ssr.vw_sigas_diage where cd_prf_responsavel in (''''' + #Prefixos + ''''''') order by cd_prf_responsavel, codigo'
select #TSQL as TSQL
-- EXEC (#TSQL)
Then you can visually check if there's something odd about it.
Or just try running that sql yourself and see if it fails or not.
From that T-SQL it returns this result :
SELECT * FROM OPENQUERY(DICOI_LINKEDSERVER,'SELECT * FROM ssr.vw_sigas_diage where cd_prf_responsavel in (''1, 2, 3''') order by cd_prf_responsavel, codigo
Notice that there's a bit to many single-quotes in that string.
When using an IN with numbers, the single-quotes are not needed.
And something is missing at the end.
... in ('+ #Prefixos +') order by cd_prf_responsavel, codigo'');';

SQL Query, column SHOULD be present, but results states, it is not

I am having a hard time grasping why this query is telling me the TaxPayerID is NOT found, when in the beginning, I am clearly checking for it and only using the databases, which should contain the TaxPayerID column in the nTrucks table.
sp_MSforeachdb
'
IF EXISTS (SELECT * FROM [?].INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''nTrucks'' AND COLUMN_NAME = ''TaxPayerID'')
BEGIN
SELECT "?", nTrucks.UnitNumber, ntrucks.Companyid, nCompanyData.CompanyName, nTrucks.Owner, nTrucks.TaxPayerID
FROM nTrucks
INNER JOIN nCompanyData ON nTrucks.CompanyID = nCompanyData.CompanyID
WHERE nTrucks.Owner like ''%Trucker%''
END
'
I am getting multiple 'Invalid column name 'TaxPayerID'.' errors, I assume it is from the databases NOT containing this column.
If anyone here can throw me a bone, a simple "you're a dummy, do it this way!", I would be very appreciative.
JF
You're a dummy! (you asked for it) :)
How to debug this error:
Locate the database that throws an error and try executing an actual SQL query on it directly to see if it will compile:
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''nTrucks'' AND COLUMN_NAME = ''TaxPayerID'')
BEGIN
SELECT nTrucks.UnitNumber, ntrucks.Companyid, nCompanyData.CompanyName, nTrucks.Owner, nTrucks.TaxPayerID
FROM nTrucks
INNER JOIN nCompanyData ON nTrucks.CompanyID = nCompanyData.CompanyID
WHERE nTrucks.Owner like ''%Trucker%''
END
It will fail.
Now you know that SQL server checks schema at query parse time rather than run time.
Then you follow #GordonLinoff suggestion and convert the SELECT query into dynamic SQL as follows:
sp_MSforeachdb
'
IF EXISTS (SELECT * FROM [?].INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''nTrucks'' AND COLUMN_NAME = ''TaxPayerID'')
BEGIN
EXEC(
''SELECT "?", nTrucks.UnitNumber, ntrucks.Companyid, nCompanyData.CompanyName, nTrucks.Owner, nTrucks.TaxPayerID
FROM [?]..nTrucks
INNER JOIN [?]..nCompanyData ON nTrucks.CompanyID = nCompanyData.CompanyID
WHERE nTrucks.Owner like ''''%Trucker%''''
'' )
END
'
(I hope I got my quotes right)
If your query is supposed to reference a central nCompareData table then remove [?].. before nCompareData

SQL pivot query error: Dynamic company names. Error - Unclosed quotation mark

I have a table called Xref.
Made up of columns ShaftecNo, CompNo, CompName.
I am trying to write a pivot query that displays [ShaftecNo],[CompNo] and then [CompName] as columns). Resulting in the following format
Code used in my stored procedure is as follows.
declare #sql nvarchar(max);
-- generate the column names
select #sql = coalesce(#sql + ',', '') + QuoteName([CompName])
from (select DISTINCT CompName from [Xrefs] WHERE CompName LIKE '[a-z]%') T;
-- replace the column names into the generic PIVOT form
set #sql = REPLACE('
select ShaftecNo, :columns:
from (SELECT ShaftecNo,CompNo,CompName FROM Xrefs INNER JOIN Product ON Xrefs.ShaftecNo COLLATE Latin1_General_CI_AS = Product.KeyCode) p
pivot (max(CompNo) for CompName in (:columns:)) as pv',
':columns:', #sql)
-- execute for the results
exec (#sql)
Please note, the LIKE command used will work if i change it to [a-c] ( only [CompName]'s that starts with a-c range) if i do a larger range like [a-r] it errors.
Msg 105, Level 15, State 1, Line 4
Unclosed quotation mark after the character string 'ALFAROME'.
Msg 102, Level 15, State 1, Line 4
Incorrect syntax near 'ALFAROME'.
The errors change for different ranges. If i take the like out completely the the query works BUT it misses out company names (i.e .Brake Engineering).
Can anyone help
It sounds like your CompName field has values that have contain single quotes, so you will need to remove/replace them when building your #sql value:
declare #sql nvarchar(max);
-- generate the column names
select #sql = coalesce(#sql + ',', '') + QuoteName(replace([CompName],'''',''))
from (select DISTINCT CompName from [Xrefs] WHERE CompName LIKE '[a-z]%') T;
-- replace the column names into the generic PIVOT form
set #sql = REPLACE('
select ShaftecNo, :columns:
from (SELECT CompNo,replace(CompName,'''''''','''') as CompName FROM a INNER JOIN Product ON Xrefs.ShaftecNo COLLATE Latin1_General_CI_AS = Product.KeyCode) p
pivot (max(CompNo) for CompName in (:columns:)) as pv',
':columns:', #sql)
-- execute for the results
exec (#sql)
Thanks for all your help. The PRINT #SQL command worked like a dream. (Thank you Nick.McDermaid) .
The problem was a random unicode ascii character - 160. Which i had to get by using ...
SELECT distinct Compname, ASCII(SUBSTRING(Compname,LEN(Compname)-1,LEN(Compname))) from [Xrefs_Temp].
Then i replaced it with blanks and it worked.
Thanks again

Sql server using variable in pivot query

I have a returned string from a query that reads:
+----------------------+
| returnquerystring |
+----------------------+
| exam1,exam2,exam3 |
+----------------------+
I am using this returned string as column names in a pivot query.
select * from (select score,exam from table1) x
pivot ( max(score) for exam in (exam1,exam2,exam3)
This query works giving me
+-------------+-----------+-----------+
| exam1 | exam2 | exam3 |
+-------------+-----------+-----------+
| 10 | 20 | 30 |
+-------------+-----------+-----------+
However I have not been able to get the pivot "in" statement to use anything but the hard coded values of exam1,exam2,exam3. For example I have used SSMS and created a query that successfully puts exam1,exam2,exam3 into #var1. However #var1 will throws and error when used in place of exam1,exam2,exam3.
declare #var1 varchar(100)
select #var1 = value from table
select * from (select score,exam from table1) x
pivot ( max(score) for exam in (#var1)
Incorrect syntax near '#var1'.
To verify that I was doing it correctly I did this and it worked.
declare #var1 int
select top 1 #var1 = id from name
select * from name where id = #var1
This provided the data row for id 1 on the name table with no error.
I have noticed in my experiments that (exam1,exam2,exam3) cannot be ('exam1,exam2,exam3') with the quotes.
I am using ColdFusion CFSCRIPT and it does appear that the single quotes are getting into the query so I tried various tests with ColdFusion functions to remove them with no success.
So I tried using the SQL Server function 'replace' around the #var1 and that throws an error about syntax at replace.
This is when I tried using an example like above in SSMS and still got errors. So by removing ColdFusion from the equation it still does not work. My thought was to send the whole declare through pivot as a query to avoid ColdFusion issues but it does not work in SSMS.
I am using SQL SERVER 8 and SSMS 11.
Any ideas on how to make this work?
examColumns = exam1,exam2,exam3
public any function qryExamScores(string examColumns) {
thisQry = new Query();
thisQry.setName("returnqry");
thisQry.setDatasource(application.datasource);
thisQry.addParam(name="columnNames",value=arguments.examColumns,cfsqltype="cf_sql_varchar");
result = thisQry.execute(sql="
select * from
(select id,score,exam
from table
where value1 = 'XXXXX'
and value2 = '11111') x
pivot
(
max(score) for exam in (:columnNames)
) p
");
returnqry = result.getResult();
return returnqry;
}
You need to use Dynamic SQL to use the value of variable(#var1) inside Pivot
declare #var1 varchar(100)='',#sql nvarchar(max)
select top 1 #var1 = value from table
set #sql = 'select * from (select score,exam from table1) x
pivot ( max(score) for exam in (['+#var1+'])) piv'
exec sp_executesql #sql
If you want to have more then one value in pivot columns use this.
SELECT #var1 += '[' + Isnull(CONVERT(VARCHAR(50), value), '') + '],'
FROM table
SELECT #var1 = LEFT(#var1, Len(#var) - 1)
SET #sql = 'select * from (select score,exam from table1) x
pivot ( max(score) for exam in (' + #var1 + ')) piv'
EXEC Sp_executesql #sql
passing exam1,exam2,exam3 as a param varchar as :parametervalue
Queryparam (or bind variables) can only be used on literals. Since "exam1,exam2,exam3" are being used as column names in this specific query, you cannot apply queryparam to them. When you do that, you are telling the database those values are simple strings. That causes an error because pivot expects object names, not strings.
Remove the queryparam and the query will work as expected. However, obviously that may expose your database to sql injection (depending on the source of columnNames). The same applies to using any dynamic SQL (exec, sp_executesql, ...). So be sure to fully validate the input before implementing this approach.
...
// build pivot statement with dynamic column names
columnNames = "exam1,exam2,exam3";
sqlString = "SELECT *
FROM (
SELECT score,exam
FROM table1
) x
PIVOT
(
MAX(score) FOR exam IN ("& columnNames &")
)
AS pvt ";
result = qry.execute( sql=sqlString ).getResult();
writeDump( result );
Edit:
Also, you should probably enclose the column names in brackets to avoid syntax errors if the values contain spaces, or other invalid characters for column names.
"[exam1],[exam2],[exam3]";

Resources