PL/SQL to DECLARE a CURSOR with an EXCEPTION [ERROR] - database

I am using Oracle Apex and I tried various forms of this code but for some reason, I keep getting the same error message and I'm frankly getting frustrated! Can someone please help me and explain why I am getting this wrong? (It's my first advanced dbms course so I hope the question isn't too stupid.)
This is my error:
ORA-06550: line 25, column 16: PLS-00201: identifier 'MARK_ASSG' must be declared
ORA-06512: at "SYS.WWV_DBMS_SQL_APEX_210200", line 673
ORA-06550: line 25, column 1: PL/SQL: Statement ignored
ORA-06550: line 26, column 16: PLS-00201: identifier 'MARK_EXAM' must be declared
ORA-06550: line 26, column 1: PL/SQL: Statement ignored
ORA-06550: line 27, column 11: PLS-00201: identifier 'COEF_ASSG' must be declared
ORA-06550: line 27, column 1: PL/SQL: Statement ignored
ORA-06550: line 28, column 10: PLS-00306: wrong number or types of arguments in call to '+'
ORA-06550: line 28, column 1: PL/SQL: Statement ignored
ORA-06512: at "SYS.DBMS_SYS_SQL", line 1658 ORA-06512: at "SYS.WWV_DBMS_SQL_APEX_210200", line 659 ORA-06512: at "APEX_210200.WWV_FLOW_DYNAMIC_EXEC", line 1829
DECLARE
mark NUMBER(4,1);
nbe INT;
no_student EXCEPTION;
I have the following tables: student, notation, result, course.
Creating table STUDENT and inserting data:
create table student
( nums number(2) primary key, name varchar(20), block number(2) );
insert into student values (10,'A',1);
insert into student values (20,'B',1);
insert into student values (30,'C',1);
insert into student values (40,'D',2);
insert into student values (50,'E',2);
insert into student values (60,'F',3);
Creating table COURSE and inserting data:
create table course
( code_course number(2) primary key, coef_assg number(4, 2), coef_exam number(4, 2) );
insert into course values(1, 0.5, 0.5);
insert into course values(2, 0.2, 0.8);
insert into course values(3, 0.3, 0.7);
insert into course values(4, 0.4, 0.6);
Creating table NOTATION and inserting data:
create table notation
( nums number(2), code_course number(2), mark_assg number(4,1), mark_exam number(4,1),
foreign key (nums) references student(nums),
foreign key (code_course) references course(code_course)
);
insert into notation values(10, 1, 15, 12);
insert into notation values(10, 2, 16, 8);
insert into notation values(10, 3, 12, 13);
insert into notation values(10, 4, 16, 17);
insert into notation values(20, 1, 12, 8);
insert into notation values(20, 2, NULL, 13);
insert into notation values(20, 3, 7, 9);
insert into notation values(20, 4, 17.5, NULL);
insert into notation values(40, 1, 7, 5);
insert into notation values(40, 2, 8, 9);
insert into notation values(40, 3, NULL, 12);
insert into notation values(40, 4, NULL, NULL);
insert into notation values(50, 1, 10, 11.5);
insert into notation values(50, 2, 5, 13);
insert into notation values(50, 3, NULL, 16);
insert into notation values(50, 4, 9, 15);
insert into notation values(60, 1, 15, 12);
insert into notation values(60, 2, 16, 8);
insert into notation values(60, 3, 12 ,13);
insert into notation values(60, 4, 16, 17);
QUESTIONS:
Define a PL/SQL program that enables inserting data in the table RESULT. The calculation of the student final mark must take into account the assignment coefficient (example: 20% = 0.2) and the exam coefficient (example: 80% = 0.8). The student can have a Zero as a mark of an assignment or exam. Thus, use the NVL function to compute the student's final mark in each course.
Define a cursor “student_mark” from tables STUDENT, NOTATION, and COURSE useful to compute the student's final mark in each course.
Define a cursor “student_No_mark” from the table STUDENT to consider the case of the student without marks. Consider the possibility of having no tuple in the STUDENT table. Raise this case as EXCEPTION and insert the values (0, ‘No_student’, NULL, NULL) into the RESULT table.
MY CODE:
DECLARE
mark NUMBER(4,1);
nbe INT;
no_student EXCEPTION;
CURSOR student_mark IS
SELECT student.nums, student.name, course.code_course, course.coef_assg, course.coef_exam, notation.mark_assg, notation.mark_exam
FROM student,course, notation
WHERE (student.nums = notation.nums) AND (notation.code_course=course.code_course);
CURSOR student_no_mark IS
SELECT nums,name
FROM student
WHERE nums NOT IN (SELECT DISTINCT nums FROM notation);
s student_mark%ROWTYPE;
sn student_no_mark%ROWTYPE;
n_mark_assg notation%ROWTYPE;
n_mark_exam notation%ROWTYPE;
n_coef course%ROWTYPE;
BEGIN
DELETE FROM result;
SELECT COUNT(*) INTO nbe FROM student;
IF (nbe=0) THEN RAISE no_student;
END IF;
OPEN student_mark;
FOR s IN student_mark LOOP
n_mark_assg := mark_assg*coef_assg;
n_mark_exam := mark_exam*coef_exam;
n_coef := coef_assg+coef_exam;
mark := (n_mark_assg+n_mark_exam)/(n_coef);
INSERT INTO result VALUES (s.nums, s.name, NULL, 0);
END LOOP;
CLOSE student_mark;
OPEN student_no_mark;
FOR sn IN student_no_mark LOOP
INSERT INTO result VALUES(sn.nums, sn.name, NULL, 0);
END LOOP;
CLOSE student_no_mark;
EXCEPTION
WHEN no_student THEN INSERT INTO result VALUES(0,'No Student', NULL, NULL);
END;

There are a lot of errors in that code. If you solve the errors you are getting now you'll run into other errors. Since this is a learning task, I'm going to point out some issues that are causing the errors and not fix your code. Note that this list might not be exhaustive.
A tip for writing any code: start with the simplest working block, then add a bit of code. If it fails, fix it first, then add a bit more code until you're done. If you write a complete block from the beginning you'll get into an endless loop of fixing errors which could result in code that is a lot worse.
DECLARE
-- tip: prefix local variables with a fixed prefix, eg l_mark instead of mark. It will make your code a lot more readable.
mark NUMBER(4,1);
nbe INT;
no_student EXCEPTION;
-- Tip: use ANSI join syntax
CURSOR student_mark IS
SELECT student.nums, student.name, course.code_course, course.coef_assg, course.coef_exam, notation.mark_assg, notation.mark_exam
FROM student,course, notation
WHERE (student.nums = notation.nums) AND (notation.code_course=course.code_course);
CURSOR student_no_mark IS
SELECT nums,name
FROM student
WHERE nums NOT IN (SELECT DISTINCT nums FROM notation);
-- all the variables below are defined as rowtype. That implies that you have to assign an entire row to them or define the column when assigning.
s student_mark%ROWTYPE;
sn student_no_mark%ROWTYPE;
n_mark_assg notation%ROWTYPE;
n_mark_exam notation%ROWTYPE;
n_coef course%ROWTYPE;
BEGIN
-- there is no ddl for a result table in the question
DELETE FROM result;
SELECT COUNT(*) INTO nbe FROM student;
IF (nbe=0) THEN RAISE no_student;
END IF;
OPEN student_mark;
FOR s IN student_mark LOOP
-- 2 things wrong in row below
-- 1. n_mark_assg is of type ROWTYPE, so you cannot assign a scalar value. Either change datatype of n_mark_assg or assign to a specific column.
-- 2. "mark_assg" and "coeff_assgn" are cursor attributes, reference them with the cursor name (eg s.mark_assg)
n_mark_assg := mark_assg*coef_assg;
n_mark_exam := mark_exam*coef_exam;
n_coef := coef_assg+coef_exam;
mark := (n_mark_assg+n_mark_exam)/(n_coef);
INSERT INTO result VALUES (s.nums, s.name, NULL, 0);
END LOOP;
CLOSE student_mark;
OPEN student_no_mark;
FOR sn IN student_no_mark LOOP
INSERT INTO result VALUES(sn.nums, sn.name, NULL, 0);
END LOOP;
CLOSE student_no_mark;
EXCEPTION
WHEN no_student THEN INSERT INTO result VALUES(0,'No Student', NULL, NULL);
END;
/

Related

SQL assignment: Using Variables and using IF statements

Okay, So here is the first question on the assignment. I just don't know where to start with the problem. If anyone could just help me get started I'd be able to figure it out probably. Thanks
Set two variable values as follows:
#minEnrollment = 10
#maxEnrollment = 20
Determine the number of courses with enrollments between the values assigned to #minEnrollment and #maxEnrollment. If there are courses with enrollments between these two values, display a message in the form
There is/are __class(es) with enrollments between __ and __..
If there are no classes within the defined range, display a message in the form
“
There are no classes with an enrollment between __ and __ students.”
.....
And here is the database to use:
CREATE TABLE Faculty
(Faculty_ID INT PRIMARY KEY IDENTITY,
LastName VARCHAR (20) NOT NULL,
FirstName VARCHAR (20) NOT NULL,
Department VARCHAR (10) SPARSE NULL,
Campus VARCHAR (10) SPARSE NULL);
INSERT INTO Faculty VALUES ('Brown', 'Joe', 'Business', 'Kent');
INSERT INTO Faculty VALUES ('Smith', 'John', 'Economics', 'Kent');
INSERT INTO Faculty VALUES ('Jones', 'Sally', 'English', 'South');
INSERT INTO Faculty VALUES ('Black', 'Bill', 'Economics', 'Kent');
INSERT INTO Faculty VALUES ('Green', 'Gene', 'Business', 'South');
CREATE TABLE Course
(Course_ID INT PRIMARY KEY IDENTITY,
Ref_Number CHAR (5) CHECK (Ref_Number LIKE '[0-9][0-9][0-9][0-9][0-9]'),
Faculty_ID INT NOT NULL REFERENCES Faculty (Faculty_ID),
Term CHAR (1) CHECK (Term LIKE '[A-C]'),
Enrollment INT NULL DEFAULT 0 CHECK (Enrollment < 40))
INSERT INTO Course VALUES ('12345', 3, 'A', 24);
INSERT INTO Course VALUES ('54321', 3, 'B', 18);
INSERT INTO Course VALUES ('13524', 1, 'B', 7);
INSERT INTO Course VALUES ('24653', 1, 'C', 29);
INSERT INTO Course VALUES ('98765', 5, 'A', 35);
INSERT INTO Course VALUES ('14862', 2, 'B', 14);
INSERT INTO Course VALUES ('96032', 1, 'C', 8);
INSERT INTO Course VALUES ('81256', 5, 'A', 5);
INSERT INTO Course VALUES ('64321', 2, 'C', 23);
INSERT INTO Course VALUES ('90908', 3, 'A', 38);
Your request is how to get started, so I'm going to focus on that instead of any specific code.
Start by getting the results that are being asked for, then move on to formatting them as requested.
First, work with the Course table and your existing variables, #minEnrollment = 10 and #maxEnrollment = 20, to get the list that meets the enrollment requirements. Hint: WHERE and BETWEEN. (The Faculty table you have listed doesn't factor into this at all.) After you're sure you have the right results in that list, use the COUNT function to get the number you need for your answer, and assign that value to a new variable.
Now, to the output. IF your COUNT variable is >0, CONCATenate a string together using your variables to fill in the values in the sentence you're supposed to write. ELSE, use the variables to fill in the other sentence.
Part of the problem is, you've actually got 3 or so questions in your post. So instead of trying to post a full answer, I'm instead going to try to get you started with each of the subquestions.
Subquestion #1 - How to assign variables.
You'll need to do some googling on 'how to declare a variable in SQL' and 'how to set a variable in SQL'. This one won't be too hard.
Subquestion #2 - How to use variables in a query
Again, you'll need to google how to do this - something like 'How to use a variable in a SQL query'. You'll find this one is pretty simple as well.
Subquestion #3 - How to use IF in SQL Server.
Not to beat a dead horse, but you'll need to google this. However, one thing I would like to note: I'd test this one first. Ultimately, you're going to want something that looks like this:
IF 1 = 1 -- note, this is NOT the correct syntax (on purpose.)
STUFF
ELSE
OTHERSTUFF
And then switch it to:
IF 1 = 2 -- note, this is NOT the correct syntax (on purpose.)
STUFF
ELSE
OTHERSTUFF
... to verify the 'STUFF' happens when the case is true, and that it otherwise does the 'OTHERSTUFF'. Only after you've gotten it down, should you try to integrate it in with your query (otherwise, you'll get frustrated not knowing what's going on, and it'll be tougher to test.)
One step at a time. Let me give you some help:
Set two variable values as follows: #minEnrollment = 10 #maxEnrollment
= 20
Translated to SQL, this would look like:
Declare #minEnrollment integer = 10
Declare #maxEnrollment integer =15
Declare #CourseCount integer = 0
Determine the number of courses with enrollments between the values
assigned to #minEnrollment and #maxEnrollment.
Now you have to query your tables to determine the count:
SET #CourseCount = (SELECT Count(Course_ID) from Courses where Enrollment > #minEnrollment
This doesn't answer your questions exactly (ON PURPOSE). Hopefully you can spot the mistakes and fix them yourself. The other answers gave you some helpful hints as well.

MS SQL Server: Treat Column As Json

I want a function (MS SQL Server 2016) that can recursively call itself to traverse a tree and to return that traversal as a single Json value. I have a working chunk of code, shown below, but I'd like to do something other than the clunky JSON_MODIFY I've used. Unfortunately, I can't find a way to make it work without it. If you comment out the line of code with the JSON_MODIFY and uncomment the next line, you'll see what I mean.
Is there a better solution?
DROP TABLE dbo.Node;
GO
DROP FUNCTION dbo.NodeList;
GO
CREATE TABLE dbo.Node (
NodeId INT NOT NULL ,
ParentNodeId INT NULL ,
NodeName NVARCHAR(MAX)
);
GO
INSERT dbo.Node(NodeId, ParentNodeId, NodeName)
VALUES (1, NULL, 'A'), (2, 1, 'B'), (3, 1, 'C'), (4, 3, 'D'), (5, 3, 'E');
GO
CREATE FUNCTION dbo.NodeList(#ParentNodeId INT) RETURNS NVARCHAR(MAX)
AS BEGIN
DECLARE #JsonOut NVARCHAR(MAX) = (
SELECT n.NodeId ,
n.NodeName ,
JSON_MODIFY(dbo.NodeList(n.NodeId), '$.x', '') AS Children
-- dbo.NodeList(n.NodeId) AS Children
FROM dbo.Node n
WHERE ISNULL(n.ParentNodeId, -1) = ISNULL(#ParentNodeId, -1)
FOR JSON AUTO
) ;
RETURN #JsonOut;
END;
GO
PRINT dbo.NodeList(NULL);
GO
The output with the JSON_MODIFY is exactly what I want...
[{"NodeId":1,"NodeName":"A","Children":[{"NodeId":2,"NodeName":"B"},
{"NodeId":3,"NodeName":"C","Children":[{"NodeId":4,"NodeName":"D"},
{"NodeId":5,"NodeName":"E"}]}]}]
... but without it, it all goes wrong ...
[{"NodeId":1,"NodeName":"A","Children":"[{\"NodeId\":2,\"NodeName\":\"B\"},
{\"NodeId\":3,\"NodeName\":\"C\",\"Children\":\"
[{\\\"NodeId\\\":4,\\\"NodeName\\\":\\\"D\\\"},
{\\\"NodeId\\\":5,\\\"NodeName\\\":\\\"E\\\"}]\"}]"}]
Thanks in advance for any ideas.
Two things:
1) The JSON_MODIFY() doesn't actually generate exactly what I want. Using the original code, the JSON_MODIFY adds an element with the name 'x' and the value '' to the value.
2) Although not a perfect answer, it is much cleaner to replace JSON_MODIFY() with JSON_QUERY() (specifically with JSON_QUERY(dbo.NodeList(...), '$'). Not only does it make more sense, this way but it gets rid of the extra 'x' artifact.
SQL obviously know that whatever comes back from JSON_MODIFY isn't really just an NVARCHAR (despite its signature), but I can't find any other way to make SQL think that an NVARCHAR is JSON.

How to get second index values of array elements according first index in postgresql9.4?

I have table called arraytable -> create table arraytable(id int, somearray int[][])
INSERT INTO arraytable(id, somearray) values(1,array[[3,5],[4,12]]);
INSERT INTO arraytable(id, somearray) values(2,array[[7,15],[13,47],[15,27],[18,97]]);
INSERT INTO arraytable(id, somearray) values(3,array[[56,1],[67,78],[105,78]]);
I have no idea how to select second index values of array elements in all rows according to particular first index values of array elements;
First, I want to select 6 array elements that have first index values smaller than 67 which would look like:
[4,12],[7,15],[13,47],[15,27],[18,97],[56,1]
And now I need to select second index values of these which would look like:
12, 15, 47, 27, 97, 1.
This is so ugly I'm sure there is a better way to do this but since nobody has answered this question, I'll post this answer bearing in mind that I don't think it's a good solution and a stable one. Don't use this in production! It's merely an exercise for me with my very limited knowledge about how multidimensional arrays work in Postgres.
It's just for the sake of answering:
with x as (
select foo.id, goo.nr, goo.first_ind, foo.somearray
from (
select *, somearray[1:array_upper(somearray,1)][1] AS first_indexes
from arraytable
) foo,
unnest(foo.first_indexes) WITH ORDINALITY goo(first_ind,nr)
where goo.first_ind < 67
)
select string_agg(z.second_ind::text, ', ' order by x.id, x.nr)
from x
join (
select *
from (
select id, first_ind, somearray[1:array_upper(somearray,1)][2:3] AS second_indexes
-- [2:3] should actually be [2] but for some reason it wouldn't work? so this is specific to data with 2 indexes
from x
) y,
unnest(y.second_indexes) WITH ORDINALITY goo(second_ind,nr)
) z on
x.id=z.id
and x.nr=z.nr
and x.first_ind=z.first_ind;
Output:
string_agg
--------------------
5, 12, 15, 47, 27, 97, 1
(1 row)
Also, {3,5} should be taken into consideration so 5 should be present in the output.

bulk insert isn't working reading .txt file into SQL Server

I'm using bulk insert to read a text file into a SQL Server table. I keep getting the same error when I try using bulk insert, even though if I take the first line of the text file, and copy the values into a plain old insert into statement, everything works. My database, stop_times, is setup as follows:
train_num int,
arrival_time time,
dept_time time,
station_name varchar(50),
seq_num, int
My .txt file has the following format
101,'04:30:00','04:30:00','San Jose',1
101,'04:35:00','04:35:00','Santa Clara',2
101,'04:40:00','04:40:00','Lawrence',3
Running
bulk insert dbo.stop_times
from 'C:\Users\amanda\Desktop\stop_times1.txt'
with(
FIELDTERMINATOR=','
)
Gives me
Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 1, column 1 (train_num).
Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 2, column 2 (arrival_time).
Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 3, column 2 (arrival_time).
etc
However, copying and pasting the first row into
insert into stop_times(train_num, arrival_time, dept_time, station_name, seq_num)
values (101, '04:30:00', '04:30:00', 'San Jose', 1);
works. I feel like I'm missing something totally obvious in the bulk insert function, but am clueless.
try this
bulk insert dbo.stop_times
from 'C:\Users\amanda\Desktop\stop_times1.txt'
with(
FIELDTERMINATOR=',',
ROWTERMINATOR = '\n'
)
IF you have column names in 1st row u need to do something like this
bulk insert dbo.stop_times
from 'C:\Users\amanda\Desktop\stop_times1.txt'
with(
FIELDTERMINATOR=',',
ROWTERMINATOR = '\n',
FIRSTROW = 2
)

MS SQL Where Like Clause Not Returning Data

I'm trying to run this query:
SELECT
USER_KEY, CHAR_KEY, CONVERT(VARCHAR,substring(char_data, 9, 16)) as CHAR_NAME
FROM CHAR_DATA0
WHERE CONVERT(VARCHAR,substring(char_data, 9, 16)) LIKE '%BrightSide08'
Which returns me nothing. (I don't understand why)
But changing the query to
SELECT
USER_KEY, CHAR_KEY, CONVERT(VARCHAR,substring(char_data, 9, 16)) as CHAR_NAME
FROM CHAR_DATA0
WHERE CONVERT(VARCHAR,substring(char_data, 9, 16)) LIKE '%BrightSide08%'
Note that the only change is ...LIKE '%BrightSide08%'
This query now returns 1 row with the data:
21045 300434 BrightSide08
examples:
(I only need the wild card to be at the beginning because)
I want the following:
0BrightSide08
1BrightSide08
But not:
0BrightSide082
1BrightSide083
This is char_data
0x0600700701003800427269676874536964653038000000000401040024002900870000006126001E0000000000000000000000007526211E0000000000000000000000006B26021E0000000000000000000000007F26031E0000000000000000000000008C26041E0000000000000000000000009A26051E0000000000000000000000009F1F000014FE180079704700A83F0000EA47193000000000000000000000F102FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16220B00000000000000000000000000E82210000000000000000000000000006722060000000000000000000000000097221800000000000000000000000000832202000000000000000000000000000000DC055802DC055C025802D007370000000600891300009B3300004D6400004D640000BCAC050076D71F00E462362D1C1300006E600A139A58000020060000000000000000000000000000DC1701000000000000000000000000004712022B0000000000000000000000004B1203320000000000000000000001004B1204130000000000000000000001004B1205320000000000000000000001003D120600000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4712080C0000000000000000000000000106090500000000000000000000010047120A190000000000000000000001004B120B0A000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1210E09000000000000000000000202C1210E09000000000000000000000202210610000000000000000000000000000A3111000000000000000000000000004D221213000000000000000000004C004D221213000000000000000000004C00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1210E09000000000000000000000202C1210E0900000000000000000000020236121800000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D221213000000000000000000004C004D221213000000000000000000004C00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA221D06000000000000000000004701DA221D06000000000000000000004701FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A3D200500000000000000000000000057222105000000000000000000008201572221050000000000000000000082012F22231400000000000000000000F4012F22231400000000000000000000F401DA221D06000000000000000000004701DA221D06000000000000000000004701FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A3D200500000000000000000000000057222105000000000000000000008201572221050000000000000000000082012F22231400000000000000000000F4012F22231400000000000000000000F401FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB373011000000000000000000000000FB373011000000000000000000000000953C3202000000000000000000000000953C32020000000000000000000000001438341D0000000000000000000000001438341D000000000000000000000000B5383690000000000000000000000000B5383690000000000000000000000000FB373011000000000000000000000000FB373011000000000000000000000000953C3202000000000000000000000000953C32020000000000000000000000001438341D0000000000000000000000001438341D000000000000000000000000B5383690000000000000000000000000B5383690000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31000000C6340000000000000200000000000000040000000000000000000000000000000000000000000000000000000D0000009C00000069CF7F0000000000FFFF000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Actually, I spoke too soon in my comment. Defining an explicit length for the portion of the substring you're going after does prevent the volatility of varchar without length from interfering with your query:
DECLARE #x TABLE(y VARBINARY(MAX));
INSERT #x VALUES(
0x0600700701003800427269676874536964653038000000000401040024002900870000006126001E0000000000000000000000007526211E0000000000000000000000006B26021E0000000000000000000000007F26031E0000000000000000000000008C26041E0000000000000000000000009A26051E0000000000000000000000009F1F000014FE180079704700A83F0000EA47193000000000000000000000F102FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16220B00000000000000000000000000E82210000000000000000000000000006722060000000000000000000000000097221800000000000000000000000000832202000000000000000000000000000000DC055802DC055C025802D007370000000600891300009B3300004D6400004D640000BCAC050076D71F00E462362D1C1300006E600A139A58000020060000000000000000000000000000DC1701000000000000000000000000004712022B0000000000000000000000004B1203320000000000000000000001004B1204130000000000000000000001004B1205320000000000000000000001003D120600000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4712080C0000000000000000000000000106090500000000000000000000010047120A190000000000000000000001004B120B0A000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1210E09000000000000000000000202C1210E09000000000000000000000202210610000000000000000000000000000A3111000000000000000000000000004D221213000000000000000000004C004D221213000000000000000000004C00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1210E09000000000000000000000202C1210E0900000000000000000000020236121800000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D221213000000000000000000004C004D221213000000000000000000004C00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA221D06000000000000000000004701DA221D06000000000000000000004701FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A3D200500000000000000000000000057222105000000000000000000008201572221050000000000000000000082012F22231400000000000000000000F4012F22231400000000000000000000F401DA221D06000000000000000000004701DA221D06000000000000000000004701FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A3D200500000000000000000000000057222105000000000000000000008201572221050000000000000000000082012F22231400000000000000000000F4012F22231400000000000000000000F401FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB373011000000000000000000000000FB373011000000000000000000000000953C3202000000000000000000000000953C32020000000000000000000000001438341D0000000000000000000000001438341D000000000000000000000000B5383690000000000000000000000000B5383690000000000000000000000000FB373011000000000000000000000000FB373011000000000000000000000000953C3202000000000000000000000000953C32020000000000000000000000001438341D0000000000000000000000001438341D000000000000000000000000B5383690000000000000000000000000B5383690000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31000000C6340000000000000200000000000000040000000000000000000000000000000000000000000000000000000D0000009C00000069CF7F0000000000FFFF000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
);
SELECT CONVERT(VARCHAR, SUBSTRING(y, 9, 16)) FROM #x
WHERE CONVERT(VARCHAR, SUBSTRING(y, 9, 16)) LIKE '%BrightSide08';
-- 0 rows
SELECT CONVERT(VARCHAR, SUBSTRING(y, 9, 16)) FROM #x
WHERE CONVERT(VARCHAR(12), SUBSTRING(y, 9, 16)) LIKE '%BrightSide08';
-- 1 row
Now, whether you should be using 12 or something else depends on what all of the possible values might be and where they may be embedded in this specific slot in your varbinary value. If you can give some more specific examples we can help further, but in the meantime, it pays to be specific rather than wishy-washy when declaring varchar.
The most likely reason is that there is some unseen character after the 08. One way this could occur is if the field is defined as a char; it would then be padded with spaces.
One way to see if there are any such values is to append characters to delimit the value:
select '|'+char_data+'|'
. . .
You have another problem in your query. You are using varchar without a length. Bad, bad, bad. In fact, the convert doesn't seem to be needed at all. You can just do:
substring(char_data, 9, 16) LIKE '%BrightSide08'
But this is equivalent to:
left(char_data, 25) LIKE '%BrightSide08'
Or, because you are looking for values at the end of the field:
right(char_data, 12) = 'BrightSide08'

Resources