SQL Server 2012 - Conversion Fails for No Possible Reason with Views - sql-server-2012

I have a view setup as
CREATE VIEW dbo.my_data_view
AS
SELECT * from dbo.my_used_data (NOLOCK)
UNION
SELECT * from dbo.my_unused_data (NOLOCK)
go
I currently don't have anything in my_unused_data table. But I expect any query made to work just fine. the following is my query:
select * from my_data_view where code = '5E7230893312001084789839'
The query is failing with the message:
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the varchar value '8E2230893319020101078983' to data type int.
This doesn't make any sense. my_used_data and my_unused_data tables have the identical schema and types so nothing can go wrong there. What I have found out is that when I have data in my_unused_data. It works fine;Otherwise it fails. Is it something special with the views or what?

Problem solved, the order of the columns where swapped for column no. 3 and 4 for my_unused_data that messed things up. I didn't realise that SQL server assumes that ordering of the column is correct when dealing with SELECT * UNION SELECT * queries

Related

Summing a Column with Multiple Data Types in SQL

I'm fairly new to SQL and am trying to write a query in sql server to get sums of documents week. My query looks like this:
SELECT
[table].[week],
SUM(ISNULL([table].[documents],0))
FROM
[table]
JOIN
(VALUES (15,187293),...other pairs...,(127,120918)) AS Outside ([ID],[Organization]) ON Outside.[ID]=[table].[ID]
AND Outside.[Organization] = [table].[Organization]
GROUP BY
week
This same query worked on a different table (formatted exactly the same) outputting documents per week, but when I run it on this table, I get the error
Msg 245, Level 16, State 1, Line 2
Conversion failed when converting the varchar value '#N/A' to data type int.
There is nothing in the documents column that looks like #N/A. How can I make this sum appropriately?
To find the offending rows, run the query:
select t.*
from table t
where id = '#N/A' or organization = '#N/A';
Or better yet:
select t.*
from table t
where try_convert(int, id) is null or try_convert(int, organization) is null;
You can fix the problem by using appropriate types in the outside set of values. That is, one or both of the values should be in single quotes so they are strings rather than numbers.

How can you convert/cast text datatypes from a PostgreSQL database to a linked MS SQL Server?

Good morning/afternoon! Been working on this problem most of the day so I figured it was time to appeal to a larger audience.
I'm running Microsoft SQL Server 2012. I have created a "Linked Server" to a PostgreSQL server. When I try to issue a query to the PostgreSQL server I get this:
SELECT *
FROM OPENQUERY(MYDB, 'SELECT notes from remote_view LIMIT 50');
Msg 7347, Level 16, State 1, Line 1
OLE DB provider 'MSDASQL' for linked server 'MYDB' returned data that does not match expected data length for column '[MSDASQL].notes'. The (maximum) expected data length is 8000, while the returned data length is 9088.
If I truncate the field (using LEFT(notes, 4000)) I can get it to work. The field on the PostgreSQL table is the "text" data type.
Any ideas how to get the data to come across without losing any of it?
UPDATE #1:
Trying to cast the value to varchar(max) yields this:
SELECT *
FROM OPENQUERY(MYDB, 'SELECT cast(notes as varchar(max)) as notes2 from remote_view LIMIT 50');
OLE DB provider "MSDASQL" for linked server "QPID" returned message "ERROR: syntax error at or near "max";
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 "QPID".
If I try to cast it as varchar(8000), it gives me this:
OLE DB provider "MSDASQL" for linked server "QPID" returned message "Requested conversion is not supported.".
I had the exact problem. I found a workaround, if length of your text data is not bigger than Postgresql's character varying size limit (10485760). You just need to change Postgresql ODBC MaxLongVarchar setting to 10485760 like the following screenshot as a first step.
After that you have three options:
You can change your text data field to character varying (10485760) at PostgreSql Server, if it's possible. The following syntax will work without any problems.
SELECT * FROM LINKEDSERVER.dbname.schemaname.tablename
If you can't change original table, you can create a view on postgresql which transforms all text fields as originaltextfield::varchar(10485760) and select from postgresql view, instead of table
SELECT * FROM LINKEDSERVER.dbname.schemaname.viewname
You can use OPENQUERY as follows
SELECT * FROM OPENQUERY(LINKEDSERVER, 'SELECT id, textfield::varchar(10485760) FROM schemaname.tablename')
Here's what I came up with that seemed to work for this issue. Break the main text field into several smaller VARCHAR fields, inside the OPENQUERY. To do this, CAST the field as a very large VARCHAR value. Then do LEFT/SUBSTRING of that value, to grab a small chunk of it. Outside of the OPENQUERY CAST each of the fields you created as VARCHAR(MAX) and concatenate them together. Using the original example, it would be something like this..
SELECT CAST(Notes1 AS VARCHAR(MAX))
+ CAST(Notes2 AS VARCHAR(MAX))
...
+ CAST(Notes5 AS VARCHAR(MAX)) AS Notes
FROM OPENQUERY(MYDB, 'SELECT
LEFT(CAST(Notes AS VARCHAR(20000),3500) AS Notes1
,SUBSTRING(CAST(Notes AS VARCHAR(20000),3501,3500) AS Notes2
...
,SUBSTRING(CAST(Notes AS VARCHAR(20000),14004,3500) AS Notes5
FROM remote_view')
You are almost done:
SELECT *
FROM OPENQUERY(MYDB, 'SELECT notes::varchar(10000) from remote_view LIMIT 50');
returned data length is 9088, so your buffer should be big enough to fit!
I had the same problem with my linked server and Openquery. I like to add my 2 cents here as solution is little different and easy compared to above solutions. The reason for taking fixed length for string is because that's how it is set in your ODBC driver. Go to your ODBC driver, Advance options and update the text box that says string length to 8000 or more to solve the problem.
Hope this helps.
Thanks!
My issue was an apostrophe in the company name. i am using openquery through a linked server to postgres 9.1
i got a data length mismatch. once i cast it to varchar 1000 it came through.
select * from OpenQuery(CMS, 'select dealer,
company::varchar(1000)
,agent,carrier,add1,city,state,zip,phone,taxid from m1') as GCP)
VARCHAR(max) can store only 8000, try the TEXT datatype instead

Update statement failing without any rows

On a SQL Server 2005 database a stored procedure that had been working starting failing. The following statement in the stored procedure was determined to be the cause of the failure:
update d set
d.location=a.[Name]+'-'+cast(a.lLocaId as varchar)
--select d.logical_name,d.location,a.[Name]+'-'+cast(a.lLocaId as varchar) as location
from hpsmp.dbo.device2m1 d
inner join hpsmp.dbo.locm1 s
on d.location=s.location
inner join hpamp.dbo.amLocation a
on s.location_code=a.lLocaId
where isnumeric(s.location_code)=1
and s.location_name<>a.[Name];
The error message is
Msg 8152, Level 16, State 2, Line 1
String or binary data would be truncated.
The statement has been terminated.
What is odd about this error is that the select statement is not returning any rows. Why would there be a truncation error in an update statement without any rows? There are no triggers on this table.
Your question is really: "What is odd about this error is that the select statement is not returning any rows. Why would there be a truncation error in an update statement without any rows? "
First, when you do the conversion to varchar you should always include a length:
set d.location = a.[Name] + '-' + cast(a.lLocaId as varchar(255))
SQL Server has different default lengths in different contexts, so this could cause a problem. Not the one you are seeing but another one.
I believe that what is happening is that SQL Server constructs the execution plan for the query and it moves the calculation of the new value of location before the filtering. In other words, it can do the calculation while reading hpamp.dbo.amLocation because that is the only table needed for the new value.
Then, it gets an error even on a row that is not being updated.
This is a bit of speculation, but SQL Server does exhibit this behavior in other places. A notorious problem is getting an error when you do:
select cast(col as datetime)
from table t
where isdate(col) = 1;
Yes, this also produces errors on invalid dates and for the same reason.
In your case, I'm not sure what the best way to fix the problem is. You could try something like:
set d.location = (case when len(a.name) < 8 then a.[Name] + '-' + cast(a.lLocaId as varchar(255)) end)
I made up the number 8, but if you set an appropriate value, then it should work.

I want to create a new table from a SQL select statement?

I want to be able to create new tables based on any SQL select statement. I have tried the following which I got the format from another question and it does not work (there are similar questions but not one that I found actually works). I keep getting an error on the SQL statement.
Msg 156, Level 15, State 1, Line 2
Incorrect syntax near the keyword 'AS'.
This is the CREATE TABLE statement:
CREATE TABLE MyNewTable
AS
SELECT *
FROM dbo.Bat
This will copy the entire table including rows
SELECT *
INTO newTableName
FROM dbo.Bat
Add WHERE 1 = 0 to copy just the table structure
If it is SQL Server (the dbo schema, default in SQL Server indicates it is SQL Server), you can do following.
select * into MyNewTable from dbo.Bat;
The SELECT INTO statement does not copy your table constraints.
You statement is a valid Oracle and MySQL statement though.
CREATE TABLE ... AS SELECT is simple (by deliberately ignoring for example the concepts of storage)
To create a table with all its lines
code:
CREATE TABLE XX AS SELECT * FROM YY ;
the result of command in mysql

Squirrel SQL Error Code 102

I'm very confused - I opened up my database in Squirrel SQL to do some SQL and I type this in my SQL entry window:
select * from *
And for whatever reason it gives me this output:
Error: Incorrect syntax near '*'.
SQLState: 42000
ErrorCode: 102
Does anyone know what this means? It's hard to do a google search because Google treats the asterisk as a special character.
I think that second * is invalid, that should be a table name:
SELECT * FROM MyTable
You need to specify the table name.
SELECT * FROM myTable
If however you knew that and you are actually looking for a way to SELECT from all your tables i'm afraid you'll have to type them one by one like this :
SELECT * FROM myTable1
UNION ALL
SELECT * FROM myTable2
UNION ALL
SELECT * FROM myTable3
...
Also remember that if you have to Select like I did on the second example, there is a problem with the way your data is organized in you database. If it's the case, you should take a look at this article on Data Normalization.