How can I query a table based on bits in a column? - sql

I created this table:
CREATE TABLE [dbo].[Subject] (
[SubjectId] INT NOT NULL,
[Name] NVARCHAR (50) NOT NULL,
[Type] BINARY(10) NULL,
CONSTRAINT [PK_Subject] PRIMARY KEY CLUSTERED ([SubjectId] ASC)
);
My thinking is that the Type column would contain a binary string like this:
0000101010
1000001010
0000001011
1000000011
What I would then like to be able to do is to for example query this table to look for particular bit being set but I am not sure how to do this. So for example how could I query the data to see what rows matched the fourth bit (from right) being set to a 1 and the second bit (from right) being set to a 1 which would result in three rows returned from the data above.

I would not recommend doing bit fiddling unless you really know what you are doing.
Normally, flags that are tinyint are quite sufficient for most purposes. However, if you have a bunch of binary flags and are very concerned about space, then declare them each independently:
Flag1 bit not null,
Flag2 bit not null,
. . .
This gives a name to each "bit" and let's the database manage the bit fiddling.
In any case, the answer to your specific question are the bit-wise operators, which are documented here.

You can query your data using bitwise operators in SQL.
See
https://msdn.microsoft.com/en-us/library/ms176122.aspx
Something like
SELECT * FROM table WHERE Type & 0x0001000 > 0
You may have to experiment with the constant you use to AND against (0x0001000). But this is saying - get me all records where the fourth bit from the right is a 1. (0x prefix denotes a binary representation)

Related

Collation in Snowflake

we created a snowflake table as shown and loaded data into into from flat file using copy into command
create or replace table temp.T_ERROR
(
ID NUMBER(38,0) Primary Key,
ERROR varchar(4) collate 'en-rtrim' NOT NULL,
)
so we saw rtrimmed values in ERROR then we tried to transfer these results into another snowflake table with no collate option set on this table
create or replace table DATA.T_ERROR_1
(
ID NUMBER(38,0) Primary Key,
ERROR varchar(4) NOT NULL,
)
ISSUE:
the DATA.T_ERROR_1 table is not getting the trimmed values from temp table instead its getting un-trimmed values which are in the original flat file
is there any other ways i can do this transfer which doesnt involve me writing rtrim ltrim or trim or every column
None of your tables have trimmed data. It only appears so in certain circumstances.
The table temp.T_ERROR has trimmed comparison semantics, and that means it compares & sorts as if it was trimmed. But assignment is not comparison, and the original value in temp.T_ERROR (which is space padded) is copied into the new table DATA.T_ERROR_1. You can check that the spaces are there with eg
SELECT '"'||ERROR||'"', LENGTH(ERROR) FROM temp.T_ERROR
As Mike Walton says elsewhere, if you have a chance to trim the spaces before the data enters Snowflake, your problems may be solved. If however you are porting an application that relies heavily on CHAR behaviour, you might be better off defining COLLATE for all the CHAR columns.
I've tested on other databases (ie Oracle) and it behaves the same way as Snowflake: if you copy from CHAR to VARCHAR you get the padding spaces, too.

How to implement searching concept using keywords in SQL

Can anyone guide how to implement the keyword search concept in SQL.Is there only “Like” operator available or any other options there?
Example: - Table:
Keyword -- Questions -- Answers
Where,pen -- Where is my pen? -- Pen is on the table
Where ,pen, kept -- where you have kept the pen -- Pen is under the
table
Input - Where is my pen?
Output should be - “Pen is on the table”
In this part I have to split the keyword from input and check the keyword with db to send the output. I should get only one output from above .Because in second row value also have “where,pen” keyword
Could anyone suggest how this logic will be implemented .
I would like to know If any keyword creating option can done in SQL part itself.
You do not want to store the keywords in a comma separated list. Instead, you want a separate table, say QuestionKeywords:
create table QuestionKeywords (
QuestionKeywordsId int identity(1, 1) primary key,
QuestionId int not null references Questions(QuestionId),
Keyword varchar(255),
constraint unq_QuestionKeywords_QuestionId_Keyword unique (QuestionId, Keyword)
);
You can then search for keywords just using equality or in.

Comparing nvarchar with bigint in sql server

I am investigating a performance issue for the following sql statement:
Update tableA
set columnA1 = columnB1
from tableB
where tableA.columnA2 = tableB.columnB2
The problem is that tableA.columnA2 is of type nvarchar(50) while tableB.columnB2 is of type bigint. My question is how sql server execute such query; does it cast bigint to nvarchar and compare using nvarchar comparing operators or does it cast nvarchar to bigint and compare with bigint comparing operators.
Another thing: if I had to leave those column types as is tableA.columnA2, tableB.columnB2' how can I rewrite this query to enhance performance?
Note: this query is only working on around 100,000 records, but it takes like forever.
Thanks in advance, really appreciate your help.
In the comparison, the nvarchar will be converted to bigint, because bigint has a higher precedence
See http://msdn.microsoft.com/en-us/library/ms190309.aspx
EDIT:
I was assuming that the conversion is always to the data type of the updated table. But this is wrong! #podiluska's answer is correct, as I tested with a statement similar to that in the question, and in the plan for the update statement, you see that the conversion is always to bigint when you compare a bigint and a nvarchar column, no matter if the bigint or the nvarchar column is on the side of the updated table: The query plan always contains an expression Scalar Operator(CONVERT_IMPLICIT(bigint,[schema1].[table1].[col1],0)) for the nvarchar column.
To help the performance, you can create a calculated column in the table B with the nvarchar column using the expression cast(ColumnA2 as bigint). Then you could build an index on this and columnB1.

unique column of type nvarchar

I have a simple table:
File: path | deleted | categories | description
I want to use the table for a Linq to SQL entity model. On the model, that column path (which is string there, nvarchar in database) can be set as primary key, but this is not the case with the Visual Studio table designer.
A path is what makes one file unique, so I have to make sure there are no duplicate paths in the table. How to achieve that ? Thanks for the time.
You make a column unique with a UNIQUE constraint, a NOT NULL UNIQUE constraint, or PRIMARY KEY constraint in SQL. But every current dbms that I can think of off the top of my head has one or more restrictions on the length of a columnm that can be constrained that way.
That means you have a fairly show-stopping problem for the most general case. A UNC path on Windows, for example, can be about 32,767 characters long.
Linux systems vary widely. 1024 and 4096 seem common, based on quick Google research.
I think you're going to have to put a unique constraint on only a surrogate key. (You have no idea how much it hurts a database guy to say that.) The problem is that you can enforce uniqueness on the surrogate, but not on the thing it takes the place of. And the thing it takes the place of is the important part.
An ID number won't work in the general case; you could easily end up with {1, /etc/adjtime}, {2, /etc/adjtime}, {3, /etc/adjtime}. You need something that somehow ties the real data to the value of the surrogate key. Something like hashbytes() would "work" in T-SQL; linq has similar functions. (But you can have collisions, like you can with almost all hash functions.)
As Martin already explained, you can create a primary key as long as the value <= 450 characters (or 900 characters, if you are able to constrain the data such that Unicode characters are not allowed). This works fine:
CREATE TABLE dbo.sample1
(
path NVARCHAR(450) NOT NULL PRIMARY KEY,
deleted BIT NOT NULL DEFAULT 0
-- ... other columns ...
);
CREATE TABLE dbo.sample2
(
path VARCHAR(900) NOT NULL PRIMARY KEY,
deleted BIT NOT NULL DEFAULT 0
-- ... other columns ...
);
Whether some visual designer in some undeclared version of Visual Studio allows you to do that, I have no idea, but you don't have to create your tables using some visual designer, do you?
If the path is liable to exceed 900 bytes, you can't make that a key, sorry. You'll have to use an IDENTITY column, some other surrogate, or a hash of the path value to use in the key. Example of a hash that will support up to a path of 4000 characters - which doesn't satisfy all potential use cases, but hopefully you are not needing to exceed 4000:
CREATE TABLE dbo.sample3
(
[path] NVARCHAR(4000) NOT NULL,
pathhash AS CONVERT(VARBINARY(900), HASHBYTES('MD5', path))
PERSISTED PRIMARY KEY
);
INSERT dbo.sample3([path])
SELECT '\\some\share\x' + REPLICATE('x', 900) + '.gif'
UNION ALL SELECT '\\some\share\x' + REPLICATE('x', 900) + '.jpg';
Try to run the insert again.
(And again, you can double the 4000 characters to 8000 characters if you can guarantee that no path will contain Unicode characters; in that case, you can use varchar(8000) instead of nvarchar(4000).)

Sql server To use nvarchar or bigint

This might be a stupid question. I need to have a Id field in a table. This Id is not a key (primary or whatever). The requirement says that user can input 10 digits in this field from the UI. This Id has no relation as of now with any otehr object in the system. Do you think If one can use nvarchar or bigint for this field. Does bigint would be an overhead for this purpose?
If you will ever perform any mathematical work with this column, then obviously an integral type is to be preferred. Alternatively, if this is a pure, opaque identifier, then a char or varchar column would seem to make more sense. And if leading zeros might be important, then obviously the integral types will not work, e.g. if storing a UK phone number, 01234 567890, you'd want that in a char column.
Edit and for bonus points, if it is an id that should always be ten digits:
CREATE TABLE T (
/* Other columns */
Id char(10),
constraint CK_ID_Valid CHECK (LEN(ID)=10 and not ID like '%[^0-9]%')
)
There are chances that business can ask you to start storing alphanumeric data in this key. I would suggest that you stick with nvarchar or varchar. Even if it remains numeric and not used anywhere in some kind of computation, it is perfectly valid to have it as varchar.
You may use NUMERIC(10,0) type
or if you dont any mathematical operation you can use nvarchar type.