Sometimes things just make more sense in SQL… Sometimes they don’t. Here is a working implementation of the SHA2 algorithm written in T-SQL.

-- If you are here looking for code to actually use in production, here you go, no need to keep reading:
SELECT HASHBYTES ( 'sha2_256' , 'The quick brown fox jumps over the lazy dog' )

To get things started, SQL doesn’t support binary shifts by default. So here are some helper functions to do bit shifting. SHA256 requires a right shift, and a right rotation. (Right rotation in turn requires a left shift). Shift are implemented by doing power of 2 multiplication/division. Every time you multiply by two, you do a single left shift. Every time you divide by two, you do a single right shift.

--
-- SHA256 implementation
--
CREATE PROCEDURE SHA256
(
@ input VARBINARY ( MAX )
)
AS BEGIN
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
DECLARE @ kvalues TABLE
(
id INT ,
val BIGINT
)
-- Initialize all of the K values
INSERT INTO @ kvalues
VALUES
( 0 , 0 x428a2f98 ),( 1 , 0 x71374491 ),( 2 , 0 xb5c0fbcf ),( 3 , 0 xe9b5dba5 )
,( 4 , 0 x3956c25b ),( 5 , 0 x59f111f1 ),( 6 , 0 x923f82a4 ),( 7 , 0 xab1c5ed5 )
,( 8 , 0 xd807aa98 ),( 9 , 0 x12835b01 ),( 10 , 0 x243185be ),( 11 , 0 x550c7dc3 )
,( 12 , 0 x72be5d74 ),( 13 , 0 x80deb1fe ),( 14 , 0 x9bdc06a7 ),( 15 , 0 xc19bf174 )
,( 16 , 0 xe49b69c1 ),( 17 , 0 xefbe4786 ),( 18 , 0 x0fc19dc6 ),( 19 , 0 x240ca1cc )
,( 20 , 0 x2de92c6f ),( 21 , 0 x4a7484aa ),( 22 , 0 x5cb0a9dc ),( 23 , 0 x76f988da )
,( 24 , 0 x983e5152 ),( 25 , 0 xa831c66d ),( 26 , 0 xb00327c8 ),( 27 , 0 xbf597fc7 )
,( 28 , 0 xc6e00bf3 ),( 29 , 0 xd5a79147 ),( 30 , 0 x06ca6351 ),( 31 , 0 x14292967 )
,( 32 , 0 x27b70a85 ),( 33 , 0 x2e1b2138 ),( 34 , 0 x4d2c6dfc ),( 35 , 0 x53380d13 )
,( 36 , 0 x650a7354 ),( 37 , 0 x766a0abb ),( 38 , 0 x81c2c92e ),( 39 , 0 x92722c85 )
,( 40 , 0 xa2bfe8a1 ),( 41 , 0 xa81a664b ),( 42 , 0 xc24b8b70 ),( 43 , 0 xc76c51a3 )
,( 44 , 0 xd192e819 ),( 45 , 0 xd6990624 ),( 46 , 0 xf40e3585 ),( 47 , 0 x106aa070 )
,( 48 , 0 x19a4c116 ),( 49 , 0 x1e376c08 ),( 50 , 0 x2748774c ),( 51 , 0 x34b0bcb5 )
,( 52 , 0 x391c0cb3 ),( 53 , 0 x4ed8aa4a ),( 54 , 0 x5b9cca4f ),( 55 , 0 x682e6ff3 )
,( 56 , 0 x748f82ee ),( 57 , 0 x78a5636f ),( 58 , 0 x84c87814 ),( 59 , 0 x8cc70208 )
,( 60 , 0 x90befffa ),( 61 , 0 xa4506ceb ),( 62 , 0 xbef9a3f7 ),( 63 , 0 xc67178f2 )
DECLARE @ hvalues TABLE
(
a BIGINT
, b BIGINT
, c BIGINT
, d BIGINT
, e BIGINT
, f BIGINT
, g BIGINT
, h BIGINT
)
-- Initialize the initial H values
INSERT INTO @ hvalues
VALUES
( 0 x6a09e667
, 0 xbb67ae85
, 0 x3c6ef372
, 0 xa54ff53a
, 0 x510e527f
, 0 x9b05688c
, 0 x1f83d9ab
, 0 x5be0cd19 )
DECLARE @ loop INT = 0
-- Length of the input binary in bytes
DECLARE @ inputLength BIGINT = LEN ( @ input )
-- Total length of the binary, including the 1 bit to append to the data, and the 8 byte length of the data
DECLARE @ totalLength BIGINT = @ inputLength + 1 + 8
-- Length that needs to padded with zeros
DECLARE @ padLength BIGINT = 64 - ( @ totalLength % 64 )
-- If the result is evenly divisible, than we don't need to pad
SET @ padLength = CASE WHEN @ padLength = 64 THEN 0 ELSE @ padLength END
-- Declare the array of zeros we need to append, and pad with the right number of zeros.
DECLARE @ zeros VARBINARY ( 55 ) = CONVERT ( VARBINARY ( MAX ), REPLICATE ( CHAR ( 0 ), @ padLength ))
-- Create the full length padded binary
DECLARE @ binary VARBINARY ( MAX ) = @ input + 0 x80 + @ zeros + CONVERT ( VARBINARY ( 8 ), ( @ inputLength * 8 ))
DECLARE @ messageSchedules TABLE
(
chunk INT
, id INT
, val BIGINT
)
-- Split the data into 4 byte words
-- Copy 64 bytes (16 words) into each 64 word chunk
-- The other 48 bits are all zero, they need to be calculated later.
--
-- Result:
-- chunk | id | value
----------------------
-- 0 | 0 | 4 BYTES FROM index (0)
-- 0 | 1 | 4 BYTES FROM index (4)
-- .
-- .
-- 0 | 15 | 4 BYTES FROM index (60)
-- 0 | 16 | 0x00000000
-- .
-- .
-- 0 | 63 | 0x00000000
-- 1 | 0 | 4 BYTES FROM index (64)
-- .
-- .
-- 1 | 16 | 0x00000000
-- 1 | 17 | 0x00000000
; WITH splitter AS
(
SELECT
0 AS id
, 1 AS pos
, SUBSTRING ( @ binary , 1 , 4 ) AS val
UNION ALL
SELECT
s . id + 1 AS id
, CASE WHEN ((( s . id + 1 ) % 64 ) < 16 ) THEN s . pos + 4 ELSE s . pos END
, CASE WHEN ((( s . id + 1 ) % 64 ) < 16 ) THEN SUBSTRING ( @ binary , s . pos + 4 , 4 )
ELSE 0 x00000000
END AS val
FROM splitter s
WHERE s . id + 1 < len ( @ binary )
)
INSERT INTO @ messageSchedules
SELECT
s . id / 64 AS chunk
, s . id % 64 AS id
, CONVERT ( BIGINT , s . val )
FROM splitter s OPTION ( MAXRECURSION 0 )
DECLARE @ rows BIGINT = @@ ROWCOUNT
-- Sadly this bit I couldn't figure out how to make more SQL-y yet.
-- For every value, you need access to previously updated values in the table,
-- Which doesn't work, since you cant see all of the values which you have updated.
--
-- We need to calculate the working values (everything we set to zero above, so anything
-- with an id larger than 15)
--
-- for every id 16 <= i < 64
-- @messageSchedules[i] = 0xFFFFFFFF
-- & (@messageSchedules[i-16]
-- + (RIGHTROTATE(@messageSchedules[i-15], 7) ^ RIGHTROTATE(@messageSchedules[i-15], 18) ^ RIGHTSHIFT(@messageSchedules[i-15], 3))
-- + @messageSchedules[i-7]
-- + (RIGHTROTATE(@messageSchedules[i-2], 17) ^ RIGHTROTATE(@messageSchedules[i-2], 19) ^ RIGHTSHIFT(@messageSchedules[i-2], 10)))
SET @ loop = 16
WHILE @ loop < @ rows * 64
BEGIN
UPDATE ws
SET ws . val = 0 xFFFFFFFF
& amp ; ( ws16 . val
+ ( dbo . ROTR32 ( ws15 . val , 7 )
^ dbo . ROTR32 ( ws15 . val , 18 )
^ dbo . SHR32 ( ws15 . val , 3 ))
+ ws7 . val
+ ( dbo . ROTR32 ( ws2 . val , 17 )
^ dbo . ROTR32 ( ws2 . val , 19 )
^ dbo . SHR32 ( ws2 . val , 10 )))
FROM @ messageSchedules ws
JOIN @ messageSchedules ws16
ON ws . chunk = ws16 . chunk AND ws . id - 16 = ws16 . id
JOIN @ messageSchedules ws2
ON ws . chunk = ws2 . chunk AND ws . id - 2 = ws2 . id
JOIN @ messageSchedules ws7
ON ws . chunk = ws7 . chunk AND ws . id - 7 = ws7 . id
JOIN @ messageSchedules ws15
ON ws . chunk = ws15 . chunk AND ws . id - 15 = ws15 . id
WHERE ws . id >= 16 AND ws . id = @ loop
SET @ loop = @ loop + 1
END
-- This is the meat of it.
-- We start with row -1, which is made up of the h values. (ai,bi...hi) store the "initial" h value for the 64 byte set.
-- a,b,c,d,e,g,h store the working values. They are all of the temp variables
-- ai,bi,ci...hi store the base value for each 64 byte set of temp variables. At every new set of 64 bytes, we start with ai,bi,ci...
-- At the end of every 64 bytes (a.id + 1) % 64 = 0, we store the new set of base values so we can add them back in at the end. (a.id + 1) % 64 = 63
; WITH abcdefgh AS
(
SELECT - 1 AS id , a , b , c , d , e , f , g , h , a AS ai , b AS bi , c AS ci , d AS di , e AS ei , f AS fi , g AS gi , h AS hi
FROM @ hvalues
UNION ALL
SELECT
a . id + 1 AS id ,
(( dbo . ROTR32 ( a . e , 6 ) ^ dbo . ROTR32 ( a . e , 11 ) ^ dbo . ROTR32 ( a . e , 25 )) -- Sigma 1
+ (( a . e & amp ; a . f ) ^ (( ~ a . e ) & amp ; a . g )) -- Ch (choice function)
+ a . h
+ ( SELECT val FROM @ kvalues WHERE id = (( a . id + 1 ) % 64 ))
+ bc . val
+ (( a . a & amp ; a . b ) ^ ( a . a & amp ; a . c ) ^ ( a . b & amp ; a . c )) -- Maj (Majority Function)
+ ( dbo . ROTR32 ( a . a , 2 ) ^ dbo . ROTR32 ( a . a , 13 ) ^ dbo . ROTR32 ( a . a , 22 )) -- Sigma 0
+ CASE WHEN ( a . id + 1 ) % 64 = 63 THEN a . ai ELSE 0 END )
& amp ; 0 xFFFFFFFF AS a ,
( a . a + CASE WHEN ( a . id + 1 ) % 64 = 63 THEN a . bi ELSE 0 END ) & amp ; 0 xFFFFFFFF AS b ,
( a . b + CASE WHEN ( a . id + 1 ) % 64 = 63 THEN a . ci ELSE 0 END ) & amp ; 0 xFFFFFFFF AS c ,
( a . c + CASE WHEN ( a . id + 1 ) % 64 = 63 THEN a . di ELSE 0 END ) & amp ; 0 xFFFFFFFF AS d ,
( a . d + ( dbo . ROTR32 ( a . e , 6 ) ^ dbo . ROTR32 ( a . e , 11 ) ^ dbo . ROTR32 ( a . e , 25 )) -- Sigma 1
+ (( a . e & amp ; a . f ) ^ (( ~ a . e ) & amp ; a . g )) -- Ch (choice function)
+ a . h
+ ( SELECT val FROM @ kvalues WHERE id = (( a . id + 1 ) % 64 ))
+ bc . val
+ CASE WHEN ( a . id + 1 ) % 64 = 63 THEN a . ei ELSE 0 END )
& amp ; 0 xFFFFFFFF AS e ,
( a . e + CASE WHEN ( a . id + 1 ) % 64 = 63 THEN a . fi ELSE 0 END ) & amp ; 0 xFFFFFFFF AS f ,
( a . f + CASE WHEN ( a . id + 1 ) % 64 = 63 THEN a . gi ELSE 0 END ) & amp ; 0 xFFFFFFFF AS g ,
( a . g + CASE WHEN ( a . id + 1 ) % 64 = 63 THEN a . hi ELSE 0 END ) & amp ; 0 xFFFFFFFF AS h
, CASE WHEN ( a . id + 1 ) % 64 = 0 THEN a . a ELSE a . ai END
, CASE WHEN ( a . id + 1 ) % 64 = 0 THEN a . b ELSE a . bi END
, CASE WHEN ( a . id + 1 ) % 64 = 0 THEN a . c ELSE a . ci END
, CASE WHEN ( a . id + 1 ) % 64 = 0 THEN a . d ELSE a . di END
, CASE WHEN ( a . id + 1 ) % 64 = 0 THEN a . e ELSE a . ei END
, CASE WHEN ( a . id + 1 ) % 64 = 0 THEN a . f ELSE a . fi END
, CASE WHEN ( a . id + 1 ) % 64 = 0 THEN a . g ELSE a . gi END
, CASE WHEN ( a . id + 1 ) % 64 = 0 THEN a . h ELSE a . hi END
FROM abcdefgh a
JOIN @ messageSchedules bc ON bc . id = (( a . id + 1 ) % 64 ) AND bc . chunk = (( a . id + 1 ) / 64 )
CROSS JOIN @ hvalues hv
)
SELECT TOP 1
CONVERT ( VARBINARY ( 4 ), a )
+ CONVERT ( VARBINARY ( 4 ), b )
+ CONVERT ( VARBINARY ( 4 ), c )
+ CONVERT ( VARBINARY ( 4 ), d )
+ CONVERT ( VARBINARY ( 4 ), e )
+ CONVERT ( VARBINARY ( 4 ), f )
+ CONVERT ( VARBINARY ( 4 ), g )
+ CONVERT ( VARBINARY ( 4 ), h )
FROM abcdefgh
ORDER BY id DESC OPTION ( MAXRECURSION 0 )
END
GO
DECLARE @ input VARBINARY ( MAX ) = CONVERT ( VARBINARY ( MAX ), 'The quick brown fox jumps over the lazy dog' )
EXECUTE SHA256 @ input = @ input -- Should be: 'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592'
SET @ input = CONVERT ( VARBINARY ( MAX ), '' )
EXECUTE SHA256 @ input = @ input -- Should be: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'

And there you have it! SHA2 implemented in SQL. Most of the algorithm is implemented in the giant CTE (abcdefgh) at the bottom of the file. If you do it completely procedural-y (while loops), you can just follow the regular Wikipedia (https://en.wikipedia.org/wiki/SHA-2) example and get a pretty clear solution.

--
-- Procedural SHA256 implementation
--
CREATE PROCEDURE SHA256
(
@ input VARBINARY ( MAX )
)
AS BEGIN
SET NOCOUNT ON
DECLARE @ kvalues TABLE
(
id INT ,
val BIGINT
)
INSERT INTO @ kvalues
VALUES
( 0 , 0 x428a2f98 ),( 1 , 0 x71374491 ),( 2 , 0 xb5c0fbcf ),( 3 , 0 xe9b5dba5 )
,( 4 , 0 x3956c25b ),( 5 , 0 x59f111f1 ),( 6 , 0 x923f82a4 ),( 7 , 0 xab1c5ed5 )
,( 8 , 0 xd807aa98 ),( 9 , 0 x12835b01 ),( 10 , 0 x243185be ),( 11 , 0 x550c7dc3 )
,( 12 , 0 x72be5d74 ),( 13 , 0 x80deb1fe ),( 14 , 0 x9bdc06a7 ),( 15 , 0 xc19bf174 )
,( 16 , 0 xe49b69c1 ),( 17 , 0 xefbe4786 ),( 18 , 0 x0fc19dc6 ),( 19 , 0 x240ca1cc )
,( 20 , 0 x2de92c6f ),( 21 , 0 x4a7484aa ),( 22 , 0 x5cb0a9dc ),( 23 , 0 x76f988da )
,( 24 , 0 x983e5152 ),( 25 , 0 xa831c66d ),( 26 , 0 xb00327c8 ),( 27 , 0 xbf597fc7 )
,( 28 , 0 xc6e00bf3 ),( 29 , 0 xd5a79147 ),( 30 , 0 x06ca6351 ),( 31 , 0 x14292967 )
,( 32 , 0 x27b70a85 ),( 33 , 0 x2e1b2138 ),( 34 , 0 x4d2c6dfc ),( 35 , 0 x53380d13 )
,( 36 , 0 x650a7354 ),( 37 , 0 x766a0abb ),( 38 , 0 x81c2c92e ),( 39 , 0 x92722c85 )
,( 40 , 0 xa2bfe8a1 ),( 41 , 0 xa81a664b ),( 42 , 0 xc24b8b70 ),( 43 , 0 xc76c51a3 )
,( 44 , 0 xd192e819 ),( 45 , 0 xd6990624 ),( 46 , 0 xf40e3585 ),( 47 , 0 x106aa070 )
,( 48 , 0 x19a4c116 ),( 49 , 0 x1e376c08 ),( 50 , 0 x2748774c ),( 51 , 0 x34b0bcb5 )
,( 52 , 0 x391c0cb3 ),( 53 , 0 x4ed8aa4a ),( 54 , 0 x5b9cca4f ),( 55 , 0 x682e6ff3 )
,( 56 , 0 x748f82ee ),( 57 , 0 x78a5636f ),( 58 , 0 x84c87814 ),( 59 , 0 x8cc70208 )
,( 60 , 0 x90befffa ),( 61 , 0 xa4506ceb ),( 62 , 0 xbef9a3f7 ),( 63 , 0 xc67178f2 )
DECLARE @ hvalues TABLE
(
id INT ,
val BIGINT
)
INSERT INTO @ hvalues
VALUES
( 0 , 0 x6a09e667 )
,( 1 , 0 xbb67ae85 )
,( 2 , 0 x3c6ef372 )
,( 3 , 0 xa54ff53a )
,( 4 , 0 x510e527f )
,( 5 , 0 x9b05688c )
,( 6 , 0 x1f83d9ab )
,( 7 , 0 x5be0cd19 )
-- Initialize temp variables
DECLARE @ a BIGINT
DECLARE @ b BIGINT
DECLARE @ c BIGINT
DECLARE @ d BIGINT
DECLARE @ e BIGINT
DECLARE @ f BIGINT
DECLARE @ g BIGINT
DECLARE @ h BIGINT
DECLARE @ s1 BIGINT
DECLARE @ s0 BIGINT
DECLARE @ ch BIGINT
DECLARE @ maj BIGINT
DECLARE @ temp1 BIGINT
DECLARE @ temp2 BIGINT
DECLARE @ loop INT
-- Length of the input binary in bytes
DECLARE @ inputLength BIGINT = LEN ( @ input )
-- Total length of the binary, including the 1 bit to append to the data, and the 8 byte length of the data
DECLARE @ totalLength BIGINT = @ inputLength + 1 + 8
-- Length that needs to padded with zeros
DECLARE @ padLength BIGINT = 64 - ( @ totalLength % 64 )
-- If the result is evenly divisible, than we don't need to pad
SET @ padLength = CASE WHEN @ padLength = 64 THEN 0 ELSE @ padLength END
-- Declare the array of zeros we need to append, and pad with the right number of zeros.
DECLARE @ zeros VARBINARY ( 55 ) = CONVERT ( VARBINARY ( MAX ), REPLICATE ( CHAR ( 0 ), @ padLength ))
-- Create the full length padded binary
DECLARE @ binary VARBINARY ( MAX ) = @ input + 0 x80 + @ zeros + CONVERT ( VARBINARY ( 8 ), ( @ inputLength * 8 ))
DECLARE @ allDataLoop INT = 0
DECLARE @ binLength INT = DATALENGTH ( @ binary )
DECLARE @ messageSchedule TABLE
(
id INT ,
val BIGINT
)
WHILE ( @ allDataLoop <> @ binLength )
BEGIN
DELETE FROM @ messageSchedule
-- Get all of the working bytes.
; WITH cte AS
(
SELECT
0 AS id
, SUBSTRING ( @ binary , @ allDataLoop + 0 + 1 , 4 ) AS val
UNION ALL
SELECT
c . id + 1 AS id
, SUBSTRING ( @ binary , @ allDataLoop + (( c . id + 1 ) * 4 ) + 1 , 4 ) AS val
FROM cte AS c
WHERE c . id < 15
)
INSERT INTO @ messageSchedule
SELECT
id ,
val
FROM cte
-- Calculate the values with indicies larger than 16 in the set of working bytes
SET @ loop = 16
WHILE ( @ loop < 64 )
BEGIN
INSERT INTO @ messageSchedule
SELECT
@ loop AS id
, 0 xFFFFFFFF & amp ; ( ws16 . val + ( dbo . ROTR32 ( ws15 . val , 7 ) ^ dbo . ROTR32 ( ws15 . val , 18 ) ^ dbo . SHR32 ( ws15 . val , 3 )) + ws7 . val + ( dbo . ROTR32 ( ws2 . val , 17 ) ^ dbo . ROTR32 ( ws2 . val , 19 ) ^ dbo . SHR32 ( ws2 . val , 10 ))) AS val
FROM @ messageSchedule ws15
JOIN @ messageSchedule ws2
ON ws2 . id = @ loop - 2
JOIN @ messageSchedule ws16
ON ws16 . id = @ loop - 16
JOIN @ messageSchedule ws7
ON ws7 . id = @ loop - 7
WHERE ws15 . id = @ loop - 15
SET @ loop = @ loop + 1
END
-- Initialize the temp variables
SELECT @ a = val FROM @ hvalues WHERE id = 0
SELECT @ b = val FROM @ hvalues WHERE id = 1
SELECT @ c = val FROM @ hvalues WHERE id = 2
SELECT @ d = val FROM @ hvalues WHERE id = 3
SELECT @ e = val FROM @ hvalues WHERE id = 4
SELECT @ f = val FROM @ hvalues WHERE id = 5
SELECT @ g = val FROM @ hvalues WHERE id = 6
SELECT @ h = val FROM @ hvalues WHERE id = 7
SET @ loop = 0
WHILE ( @ loop < 64 )
BEGIN
SET @ s1 = ( dbo . ROTR32 ( @ e , 6 ) ^ dbo . ROTR32 ( @ e , 11 ) ^ dbo . ROTR32 ( @ e , 25 )) & amp ; 0 xFFFFFFFF -- Sigma 1
SET @ ch = (( @ e & amp ; @ f ) ^ (( ~@ e ) & amp ; @ g )) & amp ; 0 xFFFFFFFF -- Ch (choice function)
SET @ temp1 = ( @ h + @ s1 + @ ch + ( SELECT val FROM @ kvalues WHERE id = @ loop ) + ( SELECT val FROM @ messageSchedule WHERE id = @ loop )) & amp ; 0 xFFFFFFFF
SET @ s0 = ( dbo . ROTR32 ( @ a , 2 ) ^ dbo . ROTR32 ( @ a , 13 ) ^ dbo . ROTR32 ( @ a , 22 )) & amp ; 0 xFFFFFFFF -- Sigma 0
SET @ maj = ( @ a & amp ; @ b ) ^ ( @ a & amp ; @ c ) ^ ( @ b & amp ; @ c ) -- Maj (Majority Function)
SET @ temp2 = ( @ s0 + @ maj ) & amp ; 0 xFFFFFFFF
SET @ h = @ g
SET @ g = @ f
SET @ f = @ e
SET @ e = ( @ d + @ temp1 ) & amp ; 0 xFFFFFFFF
SET @ d = @ c
SET @ c = @ b
SET @ b = @ a
SET @ a = ( @ temp1 + @ temp2 ) & amp ; 0 xFFFFFFFF
SET @ loop = @ loop + 1
END
-- Update the base values
UPDATE @ hvalues SET val = ( val + @ a ) & amp ; 0 xFFFFFFFF WHERE id = 0
UPDATE @ hvalues SET val = ( val + @ b ) & amp ; 0 xFFFFFFFF WHERE id = 1
UPDATE @ hvalues SET val = ( val + @ c ) & amp ; 0 xFFFFFFFF WHERE id = 2
UPDATE @ hvalues SET val = ( val + @ d ) & amp ; 0 xFFFFFFFF WHERE id = 3
UPDATE @ hvalues SET val = ( val + @ e ) & amp ; 0 xFFFFFFFF WHERE id = 4
UPDATE @ hvalues SET val = ( val + @ f ) & amp ; 0 xFFFFFFFF WHERE id = 5
UPDATE @ hvalues SET val = ( val + @ g ) & amp ; 0 xFFFFFFFF WHERE id = 6
UPDATE @ hvalues SET val = ( val + @ h ) & amp ; 0 xFFFFFFFF WHERE id = 7
SET @ allDataLoop = @ allDataLoop + 64
END
DECLARE @ result VARBINARY ( MAX ) = 0 x
SELECT @ result += CONVERT ( VARBINARY ( 4 ), val ) FROM @ hvalues
SELECT @ result
END
GO
DECLARE @ input VARBINARY ( MAX ) = CONVERT ( VARBINARY ( MAX ), 'The quick brown fox jumps over the lazy dog' )
EXECUTE SHA256 @ input = @ input -- Should be: 'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592'
SET @ input = CONVERT ( VARBINARY ( MAX ), '' )
EXECUTE SHA256 @ input = @ input -- Should be: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'

Clearly not as cool, but the procedural solution is pretty much textbook and much easier to follow.